When to Avoid the `/src` Directory in Go Projects: Best Practices Explained
You should avoid adding a top-level src folder to Go modules because it creates unnecessary nesting, clashes with $GOPATH workspace conventions, and provides no functional advantage in the module-aware era.
The golang-standards/project-layout repository explicitly warns against using a /src directory in modern Go projects. According to the project's README.md, this pattern—borrowed from Java—offers little benefit and actively causes confusion with Go's workspace and module systems. Understanding when to avoid the /src directory in Go projects ensures your repositories remain idiomatic and compatible with standard tooling.
Why the /src Directory Is Discouraged in Go
According to lines 891–894 of README.md in the golang-standards/project-layout repository, the Go community generally recommends against top-level src folders. The document outlines three primary reasons this anti-pattern persists and why it should be eliminated.
Legacy Java Conventions vs. Go Workspaces
A src folder represents a legacy Java convention that does not translate to Go's workspace model. As documented in README.md lines 891–894, Go already provides a clear workspace layout via $GOPATH (or, with modules, requires no workspace at all). Duplicating this structure inside a project adds unnecessary nesting without improving organization.
Naming Collisions with $GOPATH/src
Using src creates confusing path collisions. Lines 895–896 of README.md explain that if a project contains its own src folder while residing in $GOPATH/src, the full path becomes …/src/your_project/src/.... This redundancy is noisy and misleading, making navigation and import path reasoning unnecessarily complex.
Modules Eliminate Workspace Structuring Needs
Since Go 1.11, modules allow code to live anywhere outside $GOPATH, rendering dedicated src directories obsolete. Lines 894–896 of README.md note that adding src provides no functional advantage while hurting readability and tooling integration. The module system resolves packages relative to the go.mod file location, not a fixed workspace root.
Recommended Project Layout Without /src
Instead of nesting code under src/, place packages directly under the repository root or purpose-specific directories. This flat structure aligns with standard Go tooling expectations and simplifies import paths.
The following layout demonstrates the recommended structure:
myapp/
├─ cmd/ # entry-point binaries
│ └─ myapp/
│ └─ main.go
├─ internal/ # private packages
│ └─ auth/
│ └─ auth.go
├─ pkg/ # public libraries
│ └─ utils/
│ └─ math.go
├─ go.mod
└─ README.md
Contrast this with the discouraged approach:
myapp/
├─ src/ # ← unnecessary nesting
│ ├─ cmd/
│ │ └─ myapp/
│ │ └─ main.go
│ ├─ internal/
│ │ └─ auth/
│ │ └─ auth.go
│ └─ pkg/
│ └─ utils/
│ └─ math.go
├─ go.mod
└─ README.md
To convert an existing project, simply move the contents of src/ one level up and delete the empty folder. All import paths remain identical because Go modules resolve packages relative to the module root defined by go.mod.
Where to Place Code Instead of /src
The golang-standards/project-layout repository defines specific directories for organizing code that replace the monolithic src approach.
cmd/ for Entry Points
Executable entry points belong in cmd/. As detailed in cmd/README.md, each application should have its own subdirectory under cmd/, such as cmd/myapp/main.go, keeping main packages isolated and discoverable.
internal/ for Private Packages
Private application code should reside in internal/. According to internal/README.md, packages under this directory are protected by the Go compiler, preventing import by code outside the module boundary. This provides better encapsulation than a generic src folder.
pkg/ for Public Libraries
Public libraries intended for external use belong in pkg/. The pkg/README.md documentation describes this directory as the location for versioned, stable packages that other projects may import. Placing these directly under pkg/ rather than src/pkg/ eliminates redundant path segments.
Summary
- Avoid top-level
srcdirectories in Go modules to prevent unnecessary nesting and path confusion with$GOPATH/src. - Use modules-aware layout by placing code directly under
cmd/,internal/, orpkg/according to visibility and purpose. - Migrate legacy projects by moving
src/contents to the repository root; import paths remain unchanged due to module-relative resolution. - Follow
golang-standards/project-layoutguidelines documented inREADME.mdlines 891–896 to ensure idiomatic repository structure.
Frequently Asked Questions
Is it ever okay to use a src directory in Go?
Only at the workspace level as $GOPATH/src, never inside individual modules. According to golang-standards/project-layout, adding src to a project repository creates the problematic …/src/project/src/ path structure and offers no benefits in the module era.
How do I migrate an existing project that uses /src?
Move all directories currently inside src/ up to the repository root, then delete the empty src folder. Update your go.mod if necessary, though import paths typically remain valid since modules resolve from the root containing go.mod. Verify builds with go build ./... to ensure all package references resolve correctly.
Does using /src break Go modules?
While modules may still function technically, using /src breaks community conventions and tooling expectations. As noted in README.md lines 895–896, the redundant nesting confuses developers familiar with standard layouts and complicates integration with CI/CD systems expecting canonical structures.
What if my organization requires a src folder for policy reasons?
Challenge the requirement by demonstrating that Go modules (since version 1.11) operate independently of $GOPATH and do not benefit from additional src nesting. The golang-standards/project-layout documentation explicitly states this pattern is a legacy Java carryover inappropriate for Go's module system, making it a poor fit for modern Go development standards.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →