Standard Go Project Layout Translations
The Classic Go Project Layout: A Practical Guide to Structuring Your Repositories
Overview
If you’re building a Go application, you’ll quickly encounter the question of how to organize your repository so that it remains understandable as it grows. The Standard Go Project Layout described here is not an official Go standard. It’s a community-driven collection of patterns that have emerged over time, reflecting common practices, historical tendencies, and thoughtful refinements. This guide distills that landscape into a coherent, pragmatic description you can apply to real-world projects. It emphasizes clarity, future scalability, and the reality that every project is different. You’ll see why many teams adopt a modular approach with clear boundaries between “private” and “public” code, and you’ll learn how to balance simplicity for PoCs with structure that serves dozens of collaborators.
Key ideas you’ll encounter
- Go modules and dependency management are central. Use Go Modules unless you have a compelling reason not to. This changes how you think about the module path, vendor directories, and reproducible builds.
- The layout prioritizes explicit package boundaries: internal packages are private to your module, while pkg hosts code you may want others to reuse.
- The layout provides logical groupings for command-line tools, libraries, internal utilities, API specifications, web assets, configurations, tests, and deployment artifacts.
- It’s common to keep a light touch at first—start with a simple main module and grow the structure as your project expands.
- An explicit distinction between internal and public code helps prevent accidental imports across boundaries, a guardrail that becomes increasingly valuable as teams scale.
Core directories: what they are and why they matter
cmd: The entry points for your applications
- Purpose: Each executable gets its own directory under cmd. The directory name for each application should match the name of the executable you want to produce.
- What lives here:
- A minimal main function that wires together the application’s components.
- Small, focused code that bootstraps the rest of the system by importing from internal or pkg.
- Why it matters: Keeping main thin helps you test and reuse the core logic elsewhere, and it helps new contributors quickly see how to run an app.
internal: private application and library code
- Purpose: A private area for code you do not want others to import. This is a strong compiler-enforced boundary.
- What lives here:
- internal/app: application-specific code that should not be reused by other projects.
- internal/pkg: code shared by multiple internal components but not intended for external consumption.
- Why it matters: It enforces encapsulation and reduces the risk of accidental cross-project dependencies. If a package needs to be private, internal is the right place for it.
pkg: libraries safe for external use
- Purpose: Public libraries that other projects can import and rely on.
- What lives here:
- public packages that provide well-defined interfaces and stable behavior.
- It’s still wise to think twice about what you expose; internal can sometimes guard against overexposure.
- Why it matters: This directory serves as a clear signal that the code inside is designed for reuse beyond your immediate project, making it easier for others to depend on it.
vendor: dependencies you control (optional in modern Go)
- Purpose: A place for vendored dependencies, if you choose to vendor them.
- What lives here:
- The dependencies required to build and test your project, copied into vendor/.
- Why it matters: Some teams still vendor to isolate builds from external changes. Since Go 1.14, modules offer new options, but vendor can be useful in restricted environments or for reproducible builds.
api: specifications and contract definitions
- Purpose: OpenAPI/Swagger specs, JSON schemas, and other protocol definitions.
- What lives here:
- api/README.md often contains examples and conventions.
- Why it matters: Clear API contracts reduce integration friction with clients and other services.
web: frontend and UI-related components
- Purpose: Web application assets and server-side rendering templates.
- What lives here:
- Static assets (HTML, CSS, JavaScript) and templates for server-side rendering or serving a SPA.
- Why it matters: Keeping UI concerns isolated helps you evolve front-end and back-end independently when needed.
configs, init, scripts: operational and build tooling
configs
- Purpose: Templates for configuration files or default configurations.
- What lives here:
- Default configs, templates used by confd, consul-template, or other templating tools.
- Why it matters: Centralized configuration templates make it easier to bootstrap environments consistently.
init
- Purpose: System initialization and process management configuration.
- What lives here:
- Systemd units, upstart jobs, SysV init scripts.
- Process manager configurations (runit, supervisord).
- Why it matters: Consistent startup and lifecycle management across environments.
scripts
- Purpose: Helpers for build, analysis, deployment, and maintenance.
- What lives here:
- Shell, Python, or Make-based scripts that keep the top-level Makefile slim.
- Why it matters: Encapsulating repetitive tasks makes CI and local development smoother.
build
- Purpose: Packaging, CI, and deployment artifacts.
- What lives here:
- Cloud packaging (AMI scripts), container scripts (Docker), OS package scripts (deb, rpm, pkg).
- CI configurations (Travis, CircleCI, Drone) and related scripts.
- Why it matters: Centralizing packaging and CI config helps reproducibility and onboarding.
deployments (or deploy)
- Purpose: Deployment manifests and templates for IaaS, PaaS, and orchestrators.
- What lives here:
- Kubernetes manifests, Helm charts, Terraform templates, Docker Compose files.
- Why it matters: Keeps infrastructure as code alongside the application, reducing drift between environments.
test: testing infrastructure and data
- Purpose: Test apps, data, and utilities used during testing.
- What lives here:
- External test programs and data subdirectories.
- Why it matters: Isolating test data from production code prevents accidental leaks and keeps tests maintainable.
docs, tools, examples, third_party, githooks, assets, website
docs
Purpose: Design and user-facing documents beyond code analytics (godyocs). tools
Purpose: Supporting tooling that the project uses or provides. examples
Purpose: Sample applications or public library examples to illustrate usage. third_party
Purpose: External helpers or forked utilities. githooks
Purpose: Git hook scripts to automate checks and actions. assets
Purpose: Non-code assets like logos and other media. website
Purpose: A separate data store for a project’s website if you aren’t using GitHub Pages.
Direct directories you shouldn’t have
src
- Purpose: A Java-like pattern that many Go projects avoid. It’s common to resist a top-level src folder.
- Why you should avoid it: Go’s module system and workspace design make a top-level src directory unnecessary and potentially confusing. Embedding src-like structure can mislead developers about where to place Go code. The recommended approach is to place code directly under the module root or within the appropriate internal/pkg paths.
The practical anatomy of a Go module layout
- The /cmd directory houses standalone apps. Each subdirectory under cmd corresponds to a distinct executable. A typical main.go should be minimal and orchestrate the use of internal and public libraries rather than embedding core logic.
- The /internal boundary ensures private code remains private to the module. It’s both a convention and a compiler-enforced restriction that helps scale teams without inadvertently exposing internal implementations.
- The /pkg directory is a statement: “this is usable by others.” It’s a signal to other developers that these libraries are intended for external consumption, though you should still be mindful of API stability and semantic versioning.
- The /api and /web directories reflect a separation of concerns between contract definitions and user-facing assets. API specs guide integration; web assets support the user interface and user experience.
- The /configs, /init, /scripts, /build, and /deployments sections acknowledge the reality that applications live in environments. Your software needs not only code but the recipes that run, configure, package, and deploy it.
- The /test and /docs directories acknowledge the dual realities of robust software: tests validate behavior, and documentation clarifies usage, design decisions, and maintenance expectations.
- The common directories are intentionally generic. They’re designed to be adaptable to many kinds of Go projects, from microservices to large distributed systems.
Naming, patterns, and ongoing best practices
- Use Go Modules. The modern Go workflow hinges on modules, not GOPATH. If you adopt modules, you’ll gain reproducible builds and simpler dependency management. The module path is flexible, but the first component should preferably include a dot in older setups, and ensure you consider issues related to module path naming if you’re working with external repositories.
- Favor internal over long public APIs unless there’s a reason to expose functionality. Internal encodes your team’s intent: private to the project and not for reuse.
- Prefer explicit, well-documented APIs in pkg. Even though something is usable by others, clear interfaces and stable behavior are essential to avoiding breakages for downstream users.
- Keep the main packages small and specialized. A lean main helps you test and reason about the system while isolating business logic in the libraries that users will import.
- Leverage the “gofmt” paradigm and static analysis. Tools like gofmt, staticcheck, and a modern linter workflow help maintain style, naming, and overall quality. The older golint has seen limited maintenance; staticcheck is a preferred modern alternative.
- Readings and style references. Consider the Go naming and style guidelines from recognized sources such as the official Go docs, Effective Go, and related design discussions. These resources help you align your package names and structure with community expectations.
Badges and visibility for your project
- Go Report Card: A quick health check that can scan for gofmt correctness, vet issues, code smells, license compliance, and misspellings.
- Godoc and Pkg.go.dev: Documentation visibility that helps users understand what your project's public API looks like and how to use it.
- Release badges: Indicate the latest release version to give users confidence in the project’s maintenance status.
- Note: Badges provide at-a-glance signals about quality and activity, which is especially valuable for open source projects or libraries used by others.
Tips for adopting the layout in real projects
- Start small, iterate, and scale. If you’re learning Go, begin with a minimal main package and a single library under pkg or internal. As the project grows, gradually introduce more structure and directories where they make sense.
- Use internal to protect private implementations. As soon as you see the need to prevent external imports, move the code into internal and adjust the import paths accordingly.
- Create clear boundaries between internal and public code. When a package has value beyond your project, consider moving it to pkg and documenting its intended usage.
- Embrace vendor or modules judiciously. If you’re using modules, you’ll frequently rely on the module proxy and avoid vendor unless your environment requires it for reproducibility or offline builds.
- Document directory purposes. A short README in top-level directories like /cmd, /internal, /pkg, and /api can help new contributors understand where to place new components.
- Map your deployment to your code. Keep deployments, configurations, and CI in parallel with the code they support to minimize drift and confusion during onboarding or maintenance.
A real-world reference path
- A common pattern in the community is a project layout that aligns with these principles: an actionable division into cmd, internal, and pkg, complemented by a suite of supporting directories for configuration, scripts, CI, and deployment. While every project is unique, you’ll notice recurring motifs: modularization, explicit boundaries, and a focus on reproducibility and clarity.
- Namesake references often point to examples like iam and discussions from GopherCon talks about best practices, Go project layout patterns, and architectural guidance. While not a one-size-fits-all prescription, these references offer practical validation of how teams structure real-world Go projects.
Notable notes and caveats
- The layout described here is a guide, not a mandate. Some teams may find themselves in a different pattern that better fits their domain or organizational constraints.
- The “src” pattern is generally discouraged in modern Go projects. The Go workspace and module approach anticipate that you place your code directly within the module’s tree rather than within a Java-like src directory.
- The project layout evolves with Go toolchains. Go Modules and other tooling continue to shape best practices. Stay informed about the latest recommendations from the Go community to ensure compatibility and maintainability.
Conclusion: balancing simplicity and growth
A well-structured Go project is a living instrument. It should be simple enough to be understood by a new contributor within a short time, yet capable of scaling to support dozens of developers and multiple applications. The Standard Go Project Layout provides a pragmatic blueprint that aligns with how teams think about modularity, encapsulation, and reusability. It helps you organize code around clear responsibilities, minimize hidden dependencies, and provide a smooth path for onboarding, testing, and deployment.
While you don’t need to implement every folder right away, adopting the core ideas—cmd for executables, internal for private code, pkg for shareable libraries, and a thoughtful collection of support directories for API specs, web assets, configs, scripts, and deployment—will yield long-term dividends. It reduces cognitive load during development, makes changes more predictable, and makes your project friendlier to new contributors, users, and collaborators.
Images and visuals
Note: The input for this guide did not include embedded images. If you plan to publish this as a blog post, consider adding diagrams that visualize the relationships between cmd, internal, and pkg, or a map-like diagram showing how /api, /web, /configs, /build, and /deployments relate to one another within a typical Go project. Visuals can reinforce the boundary concepts and help readers grasp the architecture at a glance.
Enjoying this project?
Discover more amazing open-source projects on TechLogHub. We curate the best developer tools and projects.
Repository:https://github.com/golang-standards/project-layout
GitHub - golang-standards/project-layout: Standard Go Project Layout Translations
The Classic Go Project Layout: A Practical Guide to Structuring Your Repositories. This guide distills the community-driven collection of patterns for organizin...
github - golang-standards/project-layout


