4.6 KiB
4.6 KiB
Directory Layouts
Universal Layout (Most Projects)
project/
├── cmd/ # Entry points - ONE subdirectory per main package
│ ├── server/ # Main application #1
│ │ └── main.go
│ ├── client/ # Main application #2
│ │ └── main.go
│ └── migrate/ # Main application #3
│ └── main.go
│ └── cli/ # Main application #4
│ └── main.go
│ └── worker/ # Main application #5
│ └── main.go
├── internal/ # Private application code (`internal/` MUST be used for non-exported packages)
│ ├── app/ # Application initialization
│ ├── config/ # Configuration loading
│ ├── handler/ # HTTP/request handlers
│ ├── model/ # Data models/domain
│ └── service/ # Business logic
├── pkg/ # Public libraries (optional - only if useful to others)
│ └── logger/
│ └── logger.go
├── api/ # API definitions (optional)
│ └── openapi.yaml
├── configs/ # Configuration files (optional)
│ └── config.yaml
├── scripts/ # Build/deployment scripts (optional)
├── go.mod
├── go.sum
├── Makefile # Build automation
├── .gitignore # Git ignore patterns
├── .golangci.yml # Linter configuration
├── LICENSE # License file
└── README.md
Small Projects (Single Binary)
For simple tools, keep it minimal:
my-tool/
├── cmd/
│ └── my-tool/
│ └── main.go # Single main package
├── internal/
│ └── core.go # Application logic
├── go.mod
├── Makefile # Build automation (optional but recommended)
├── .gitignore # Git ignore patterns
├── .golangci.yml # Linter configuration (optional)
├── LICENSE # License file (recommended)
└── README.md
Libraries (Reusable Code)
my-library/
├── example/ # Example
├── logger/ # Public package
│ ├── logger.go
│ └── logger_test.go
├── internal/
│ └── impl/ # Private implementation details
│ └── core.go
├── go.mod
├── go.sum
├── Makefile # Build automation
├── .gitignore # Git ignore patterns
├── .golangci.yml # Linter configuration
├── LICENSE # License file
└── README.md
Key points for libraries:
- Put public API in root-level directories (e.g.,
logger/) - Use
internal/for private implementation - Don't use
cmd/(unless you have example binaries)
The cmd/ Directory Convention
CRITICAL: All main packages must reside in cmd/. cmd/ MUST contain only main.go with minimal logic — parse flags, wire dependencies, call Run(). NEVER put business logic in cmd/ — it belongs in internal/ or pkg/.
Single Application
cmd/
└── myapp/
└── main.go // package main
Multiple Applications
When you need multiple binaries (e.g., server, CLI tool, migration utility):
cmd/
├── server/
│ └── main.go // Runs the API server
├── client/
│ └── main.go // CLI client tool
├── worker/
│ └── main.go // Background worker
└── migrate/
└── main.go // Database migration utility
Each main.go:
- Declares
package main - Has its own
func main() - Can be built independently:
go build ./cmd/...
Building all binaries:
go build ./cmd/... # Build all main packages
go build ./cmd/server # Build specific binary
Common Mistakes to Avoid
Don't Do This
myproject/
├── src/ # Go doesn't use /src (Java pattern)
├── main.go # Don't put main at root
├── utils/ # Generic package name
├── helpers/ # Generic package name
└── common/ # Generic package name
Do This Instead
myproject/
├── cmd/
│ └── myapp/
│ └── main.go # Main in cmd/
├── internal/
│ ├── util/ # Specific utility names
│ └── format/ # Or domain-specific names
└── pkg/ # Only if useful to others