# When to Avoid the `/src` Directory in Go Projects: Best Practices Explained

> Learn why you should avoid the top-level src directory in Go projects. Discover best practices for cleaner, more efficient Go module organization.

- Repository: [golang-standards/project-layout](https://github.com/golang-standards/project-layout)
- Tags: best-practices
- Published: 2026-03-06

---

**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`](https://github.com/golang-standards/project-layout/blob/main/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`](https://github.com/golang-standards/project-layout/blob/main/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`](https://github.com/golang-standards/project-layout/blob/main/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`](https://github.com/golang-standards/project-layout/blob/main/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`](https://github.com/golang-standards/project-layout/blob/main/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:

```text
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:

```text
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`](https://github.com/golang-standards/project-layout/blob/main/cmd/README.md), each application should have its own subdirectory under `cmd/`, such as [`cmd/myapp/main.go`](https://github.com/golang-standards/project-layout/blob/main/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`](https://github.com/golang-standards/project-layout/blob/main/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`](https://github.com/golang-standards/project-layout/blob/main/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 `src` directories** in Go modules to prevent unnecessary nesting and path confusion with `$GOPATH/src`.
- **Use modules-aware layout** by placing code directly under `cmd/`, `internal/`, or `pkg/` 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-layout`** guidelines documented in [`README.md`](https://github.com/golang-standards/project-layout/blob/main/README.md) lines 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`](https://github.com/golang-standards/project-layout/blob/main/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.