Basic Golang Project Structure
Understanding the standard layout for Go applications
Go projects follow a conventional structure that makes code organization clear and maintainable. While Go doesn't enforce a strict project layout, there are widely accepted conventions that help teams collaborate and make projects easier to understand. This guide shows the basic structure for a typical Go application.
Standard Project Layout
Root Files
go.mod
Defines the module path and Go version. Lists all dependencies with their versions. Created with go mod init github.com/username/project.
go.sum
Contains cryptographic checksums of all dependencies. Ensures reproducible builds. Auto-generated by Go.
main.go
The entry point for simple applications. Contains the main() function. For larger projects, use cmd/ instead.
README.md
Project documentation, installation instructions, usage examples, and contribution guidelines.
.gitignore
Excludes build artifacts, IDE files, and environment-specific files from version control.
Directory Structure
cmd/
Contains the main applications for your project. Each subdirectory is a separate executable. This allows multiple binaries in one project (e.g., cmd/server, cmd/cli).
Example: cmd/web/main.go for a web server, cmd/migrate/main.go for database migrations.
internal/
Private application code that cannot be imported by other projects. Go enforces this restriction. Use for business logic, handlers, models, and database code specific to your application.
Common subdirectories: handlers/, models/, database/, config/, middleware/.
pkg/
Public library code that can be imported by other projects. Use for reusable components, utilities, and shared libraries.
Example: pkg/utils/ for helper functions, pkg/validator/ for validation logic.
api/
API definitions, protocol buffer files, or OpenAPI specs. Useful for documenting and versioning your API.
configs/
Configuration files (YAML, JSON, TOML, .env). Store default configurations and environment-specific settings.
migrations/
Database migration files. Use tools like golang-migrate or sql-migrate to manage schema changes.
tests/
Integration tests and test fixtures. Note: Go convention is to put *_test.go files next to the source files.
docs/
Additional documentation, API specs, architecture diagrams, and design documents.
Best Practices
-
Keep it simple: Small projects don't need all directories. Start with
main.goand add structure as needed. - Use internal/ for app-specific code: Prevents external imports and keeps your code encapsulated.
-
Put test files next to source: Go's testing convention uses
*_test.gofiles in the same package directory. -
Organize by feature for larger projects: Instead of
internal/handlers/, considerinternal/user/,internal/order/(domain-driven design). -
Version control go.sum: Always commit
go.sumto ensure reproducible builds.
Quick Start Example
# Initialize a new Go module
go mod init github.com/username/my-go-project
# Create basic structure
mkdir -p cmd/app internal/handlers internal/models
mkdir -p pkg/utils configs migrations tests docs
# Create main.go
cat > main.go << 'EOF'
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}
EOF
# Run the project
go run main.go