In a Go package spread over several files, where does the package comment belong?
answer
- every file repeats the package clause
- only one of them should carry prose
- several comments get combined unpredictably
- a file that holds no code at all
- doc.go
basics
~20 sIn exactly one file, as a comment block directly above that file's package clause with no blank line between. When the overview grows long, the convention is a doc.go file holding only that comment and the package clause.
solid answer
~50 sEvery file repeats the `package console` clause, but only one of them should carry the package comment, written as a block immediately above the clause and starting with the word `Package` and the package name. If several files each carry one, the tools combine them in an order you do not control, which is how packages end up with a duplicated or scrambled overview. Once that comment is more than a few lines — an overview, a getting-started paragraph, a note on concurrency safety — the convention is to move it into its own file, `doc.go`, containing nothing but the comment and the package clause. That keeps a long prose block out of the way of real code, gives the overview a stable home that survives refactoring of the implementation files, and makes it obvious to the next contributor where to add to it.
code
go · 6 lines// Package console renders an interactive admin terminal for internal services.
//
// Create a session with NewSession and drive it until the operator quits.
// A session owns the terminal it is given and is not safe for concurrent use
// by multiple goroutines.
package consolego deeper
Remember that the package comment goes immediately above one file's package clause and opens with the word Package followed by the package name. Know that doc.go is a normal hand-written source file, not generated.
Explain why only one file should carry it — documentation is gathered from every file in the directory, so duplicates get combined in file-name order — and when moving it to doc.go is worth the extra file.
Show judgment about what the overview owes a first-time reader: purpose, entry points, ownership and concurrency rules, with per-declaration reference material left on the declarations. Mention build constraints as a reason to isolate the comment.
Treat the package overview as the thing that decides whether another team adopts or forks your library, and set the expectation that a new package is not done until its front page answers how do I start and what must I not do.
## The rule A **package comment** is the doc comment attached to the `package` clause. Like every Go doc comment it binds by adjacency: it is the comment block immediately preceding `package name`, with no blank line in between. ```go // Package console renders an interactive admin terminal for internal // services. It is intended to be embedded in operator tools that are run // by hand rather than by automation. package console ``` The conventional opening is the literal word `Package` followed by the package name, so the sentence still identifies itself when a directory listing of packages prints one synopsis line per package. ## One file, not all of them A Go package is a set of files in one directory, each of which repeats the same `package` clause. Only one of those files should carry the package comment. The documentation tools gather package documentation from every file in the package, so if three files each open with a paragraph, the reader gets all three concatenated in an order determined by file name rather than by your intent — an overview that reads like it was assembled by accident, and one that silently changes shape when somebody adds `aaa_helpers.go`. So: pick a file and keep the comment there. ## What doc.go is for For a small package, the natural home is the file that holds the main type — `session.go` for `package console`. But a good package overview grows: what the package is for, the two or three entry points, a short usage sketch, concurrency guarantees, a pointer at the examples. Once that is twenty lines of prose sitting on top of a source file, it pushes the actual code below the fold and every reader of `session.go` scrolls past it. The convention is a file called **`doc.go`** containing exactly two things: the package comment and the package clause. Nothing else — no declarations, no imports. ```go // Package console renders an interactive admin terminal for internal services. // // Create a session with NewSession and drive it until the operator quits. // A session owns the terminal it is given and is not safe for concurrent use. package console ``` What this buys you: - **A stable home.** Implementation files get split, renamed and merged; `doc.go` does not, so the package overview never has to move and never accidentally gets deleted along with a refactored file. - **Discoverability.** A contributor looking for "where do I document this package" finds a file whose name answers the question. - **Clean code files.** No source file opens with half a screen of prose. - **Platform independence.** Files carrying build constraints are excluded from builds for other platforms, and a package comment living in such a file disappears with it. A constraint-free `doc.go` is always compiled in, so the docs exist for every target. The cost is a file that contains no code, which occasionally surprises newcomers from languages where such a file would be meaningless. That is the whole trade, and it is why very small packages often skip it. ## Commands A `package main` also gets a package comment, and there it documents **the command**: what the binary does, its flags, its exit behaviour. The convention is to lead with the command name — `// Consolectl runs an interactive admin console against a service.` — and this comment is precisely what a reader sees when they look the command up, since a command exports nothing else worth reading. ## What belongs in it Think of it as the front page a stranger lands on: what problem the package solves, the one or two calls that get them started, any rule they must obey ("the caller must close what New returns", "a Session is not safe for concurrent use"), and where to look next. What does not belong: change logs, TODO lists, internal design debates, and API reference material that should be on the individual declarations instead. If a paragraph is really about one function, it belongs on that function, where the reader will be standing when they need it. ## Checking it Read what you wrote the way a user will, with `go doc` on the package. Prose that looked fine as a block of `//` lines in an editor sometimes turns out to have lost its paragraph breaks or run its list lines together, and reading the rendered form is the fastest way to notice.
- What happens if two files in the same package each carry a package comment?Nothing fails to build, which is the trap. The documentation tools collect package documentation from every file in the directory, so the reader gets the paragraphs combined in an order driven by file names rather than intent. The result is a duplicated or oddly sequenced overview that changes when someone adds a file, so keep the comment in exactly one place.
- How does a package comment differ for a package main command?It documents the binary rather than an importable API: what the command does, its flags and its behaviour on exit. The convention is to open with the command's name rather than the word Package, because that is the name the reader typed. For a command it is often the only documentation there is, since nothing is exported.
- Why is a doc.go file preferred over putting the overview on a file with build constraints?A file excluded by a build constraint is excluded from documentation for that configuration too, so a package comment living there vanishes for every platform the file does not apply to. A constraint-free doc.go is always part of the package, which keeps the overview visible regardless of target.
- What should stay out of a package comment and go on the declarations instead?Anything specific to one function or type: parameter meaning, error cases, method contracts. The package comment is the front page — purpose, entry points, rules that apply package-wide, and a pointer at examples. Reference material duplicated there drifts out of sync with the declaration it describes and is read at the wrong moment.
saying these in an interview costs you the question
- Puts a package comment at the top of every file in the package
- Separates the comment from the package clause with a blank line
- Thinks doc.go is generated output rather than hand-written prose
- Fills doc.go with declarations, imports or helper code
- Starts the comment with something other than the package name
- Uses the package comment as a change log