skip to content

Doc Comments and Examples

A Go doc comment is a full sentence starting with the identifier it documents, and an Example function is documentation the toolchain compiles and runs. Both are conventions with teeth.

part ofGo (Golang)overview, primer and where to startread it →
on this pageshow

questions

4

Why should a Go doc comment on an exported function begin with the function's name?

level: juniorimportance: must knowfreq 60%

answer

  1. the tool shows the text somewhere else
  2. package listings print one sentence only
  3. no blank line before the declaration
  4. a comment opening with This has no subject
  5. name it, then say what it does

basics

~20 s

Go's documentation tools lift the comment away from the declaration and show it on its own, so the sentence has to name its own subject. Starting with the identifier also makes the first sentence a self-contained one-line summary in package listings.

solid answer

~50 s

A Go doc comment is just the comment block sitting immediately above a declaration with no blank line between them, and the convention is that it is a complete sentence starting with the name being documented: `// Run draws the console and blocks until the user quits.` The tools extract that text and render it away from the code, and the first sentence alone becomes the one-line synopsis in a package listing, in `go doc` output and in search results. A comment that opens with "This function returns..." reads as an orphan there, because nothing on that line says what it is about. The same rule applies to types, constants, variables and the package clause, where the comment starts `// Package console ...`. Nothing enforces it, so it is a review habit, not a compile error.

code

go · 8 lines
go
// Package console renders an interactive admin terminal for internal services.
package console

// NewSession returns a session that reads commands from r and draws to w.
// The caller must close the returned session to restore the terminal.
func NewSession(r io.Reader, w io.Writer) (*Session, error) {
	// ...
}

go deeper

for a junior

Be ready to write one on the spot: a complete sentence starting with the identifier, placed immediately above the declaration with no blank line. Know that Go has no annotation syntax for docs.

for a middle

Explain the mechanism, not just the rule: the tools extract the text and print the first sentence alone as a synopsis, which is why the sentence must name its own subject and front-load the point.

for a senior

Show what you enforce in review — contract over implementation, a sentence on every exported name, and consistency with the standard library's declarative voice, since nothing in the toolchain will fail a build over any of it.

for a principal

Frame documentation as part of the package's public surface: the synopsis is what a team scanning for a library actually reads, so treat a missing or misleading first sentence as an API defect, not a style nit.

## What a Go doc comment actually is Go has no separate documentation syntax — no `@param`, no tags, no XML. A **doc comment** is an ordinary comment that happens to sit in the right place: directly before a top-level declaration (`func`, `type`, `const`, `var`) or before the `package` clause, **with no blank line in between**. That adjacency is the whole binding mechanism. Insert one blank line and it stops being documentation and becomes an ordinary comment that no tool will ever show: ```go // Save writes the session to disk. <- doc comment func Save() error { ... } // Save writes the session to disk. func Save() error { ... } <- just a comment; go doc shows nothing ``` ## Why the first word is the identifier The reason is mechanical rather than aesthetic. Documentation tooling *moves the text*. `go doc strings.TrimSpace` prints the comment next to a signature you did not write; a package index prints only the **first sentence** of each declaration's comment as a synopsis, in a list of dozens; a search result shows that sentence with no surrounding code at all. In every one of those places the reader may have no other clue what the sentence is about. So the convention is: a complete sentence whose subject is the identifier. ```go // NewSession returns a session bound to r and w. The caller must // call the session's Close method to restore the terminal. func NewSession(r io.Reader, w io.Writer) (*Session, error) ``` Read that first sentence alone, in a list, and it still works. Compare: ```go // This creates a new session. Don't forget to close it! ``` Extracted into an index, that is a sentence about nothing. It is also unsearchable: a colleague grepping the tree for `NewSession returns` finds the documented one and misses the other. A useful side effect is the grammatical discipline it imposes. Because the sentence starts with the name, you are pushed straight into declarative present tense — "returns", "reports whether", "draws", "blocks until" — which is exactly the register the standard library uses. "Reports whether" in particular is the conventional opening for a function returning `bool`. ## It applies to every documented kind - **Functions and methods:** `// Run draws the console and blocks until ctx is done.` - **Types:** `// A Session is a live admin console attached to one terminal.` The leading article is fine and common in the standard library. - **Constants and variables:** name them the same way; a `var` block can also take one comment for the whole group. - **The package:** `// Package console renders an interactive admin terminal.` Package comments always start with the word `Package` followed by the package name. ## What belongs in the text Document the **contract**, not the implementation. What does it return, what does it do to its arguments, what must the caller do afterwards, what happens on error, is it safe to call from several goroutines? Those are the questions a reader has, and they are the ones the code itself cannot answer at a glance. A line-by-line narration of the body is worse than nothing, because it goes stale the first time somebody edits the body and does not read the comment. Front-load it. Because only the first sentence survives into the synopsis, the most important fact must be in it, and the sentence should end with a period followed by a space or newline so the tools can find the boundary. ## Unexported names The convention is written for exported identifiers, since those are what a package's users read. It is still worth documenting non-obvious unexported functions in the same style — the next maintainer is a reader too, and `go doc -u` will show them on request. What you should not do is leave an exported identifier undocumented and assume the name carries it; anything another team imports deserves a sentence. ## Enforcement Nothing in the compiler cares. `gofmt` will reformat the comment's layout but will not write it for you, and it will not complain that the first word is wrong. This is a code-review convention, held up by the fact that every package in the standard library follows it, so a comment that breaks the pattern is visibly foreign to any Go reader.

  • Does the same rule apply to a type or to the package clause?
    Yes. A type's comment starts with the type name, often with an article: `// A Session is a live admin console attached to one terminal.` A package comment starts with the word `Package` and the package name: `// Package console renders an interactive admin terminal.` Constants and variables follow the same pattern, and a grouped `var` block may take a single comment covering the group.
  • How much of a doc comment does a package listing actually show?
    Only the first sentence — the text up to the first period followed by a space or a newline. That synopsis is what appears next to each declaration in a package index and in search results, so the most important fact has to be in sentence one. Everything after it is shown only when the reader opens the full entry.
  • What stops a comment above a declaration from being its doc comment?
    A blank line. The comment block must be immediately adjacent to the declaration; a single empty line between them turns it into an ordinary comment that documentation tools ignore entirely. The same happens if the comment is indented inside the function body rather than placed above the declaration.
  • Are doc comments worth writing on unexported functions?
    The convention targets exported names, because those are what importers read, but a tricky unexported helper deserves the same treatment for the next maintainer. `go doc -u` displays unexported declarations and their comments when you ask for them. The cost is one sentence; the benefit is that the contract is written down somewhere other than the body.

It is like a dictionary entry: the headword comes first because the entry will be read out of order, on its own line, far from wherever you wrote it.

saying these in an interview costs you the question

  • Thinks any comment above the declaration counts, blank line or not
  • Opens with This function returns, which reads as an orphan in an index
  • Believes the compiler or gofmt enforces the convention
  • Narrates the implementation line by line instead of the contract
  • Assumes exported names with good names need no comment at all
  • Buries the key fact in the third sentence, so the synopsis says nothing
open as a page

In a Go package spread over several files, where does the package comment belong?

level: middleimportance: should knowfreq 42%

basics

~20 s

In 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.

open as a page

A Go library's doc comment shows a usage snippet that no longer compiles. How do you stop that drift?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Move the snippet out of the comment into a runnable Example function in a _test.go file. It is compiled with the package, so an API change breaks the build, and a // Output: comment makes go test check what it prints.

open as a page