Go project layout
Skill Amey-Thakur/AI-SKILLS/skills/systems-languages/go-project-layout
Plug-and-play skills and prompts for every AI coding agent
npx -y skills add Amey-Thakur/AI-SKILLS --skill go-project-layoutAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 19 days oldThe repository was created 19 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Organize Go packages by domain with internal boundaries, consumer-side interfaces, and structure that grows on demand. Use when starting a Go project or refactoring one into clearer packages.
SKILL.md
3.1 KB, as published. Nobody here has run it
Go project layout
Go rewards starting small and letting structure emerge from real dependencies. Packages are the unit of design: name them by what they provide, point their dependencies one way, and keep interfaces where they are consumed.
Method
- Start flat; split on pressure. A new service begins as one
main package or
main.goplus one library package; introduce packages when a file group has a coherent name and other code wants only part of it. Pre-built empty scaffolds (pkg/,utils/,models/,services/) invent boundaries before knowing them; theutilsgrab-bag in particular is a queue of unfiled code (same smell as python-project-structure). - Name packages by what they provide.
storage,billing,token: short, lower-case, no stutter (billing.Invoice, notbilling.BillingInvoice). A package name is part of every call site; if you cannot name it without "util", "common", or "helpers", the contents belong elsewhere. - Use internal/ as the API boundary. Anything under
internal/is uncompilable by outside modules: put everything there by default, exporting only the packages you intend others to import. For applications,cmd/<binary>/main.goas thin entrypoints (parse flags, wire dependencies, call into internal; the python-cli-tools separation) and all logic importable and testable. - Define interfaces where they are used, sized to need. The
consumer declares the 1-3 method interface it requires
(
type Store interface { Get(...) }) and the concrete type satisfies it implicitly; producers exporting fat interfaces recreate Java's ceremony without its tooling. Accept interfaces, return concrete types. - Keep the dependency arrows one-way. Domain packages do not
import transport or storage details;
cmdwires concretes into constructors (NewServer(store, clock)): plain constructor injection, no framework (see layered-architecture, dependency-inversion instincts). Import cycles are always a misplaced concept; extract the shared type downward into its own package. - Let the module be the unit of versioning. One module per
repo until you need independent versioning;
go.modat the root, packages underneath. Multi-module repos andpkg/layers are big-org tools with real costs; adopt them for a demonstrated reason (see monorepo-vs-polyrepo), not because a template did.
Boundaries
- Libraries invert some defaults: the root package is the product,
examples and internal test helpers hide in
internal/, and API surface discipline follows api-surface-minimalism. - Generated code (protobufs, mocks) lives in clearly-marked packages out of the human-edit path; do not hand-edit or review-nitpick it.
- Layout conventions from other ecosystems (src/, deep nesting, package-per-class) fight Go tooling and readability; when in doubt, mirror the standard library's shape.