skip to content

A Go doc comment renders as one run-on paragraph — which doc comment syntax rules were missed?

level: middleimportance: nice to knowfreq 26%

answer

  1. it is not markdown
  2. an empty comment line is the paragraph break
  3. indentation means preformatted, not emphasis
  4. one hash and a space is the only heading
  5. brackets around a name make a doc link

basics

~20 s

Go doc comments use a tiny syntax: an empty comment line separates paragraphs, indented lines become a code block or list, hash-space makes a heading, brackets around a name make a link. Other markdown is literal.

solid answer

~40 s

Go recognises only a small formatting syntax in doc comments, so markdown habits silently produce a wall of text. Paragraphs are separated by an empty `//` line — without one, every sentence joins the same paragraph. A span of lines indented past the `//` becomes a preformatted code block, so accidentally indented prose is shown as code. A list is a span of indented lines starting with a dash, star, plus or bullet, or a number followed by a dot or parenthesis, and it needs a blank comment line before it or it merges into the paragraph above. A heading is a line beginning with `# ` — `##` and `**bold**` are literal text. `[Name]` and `[pkg.Name]` become documentation links, plain URLs auto-link, and a paragraph starting `Deprecated:` marks the identifier deprecated.

code

go · 14 lines
go
// Package cache stores rendered pages in memory.
//
// # Eviction
//
// Entries leave the cache in two ways:
//
//   - the lifetime passed to [New] expires, or
//   - [Cache.Purge] removes them explicitly.
//
// A minimal use looks like:
//
//	c := New(time.Minute)
//	c.Put("k", []byte("v"))
package cache

go deeper

for a junior

Know that an empty comment line is what starts a new paragraph, and that indenting lines shows them as code. Those two rules alone fix most unreadable comments.

for a middle

Be able to list the recognised constructs — paragraphs, indented preformatted blocks, bullet and numbered lists, hash-space headings, bracketed doc links and the Deprecated paragraph — and say what happens to anything else.

for a senior

Demonstrate reviewing documentation as rendered output rather than as a diff, and catching the quiet failures: a literal bracketed name whose link did not resolve, or an indented sentence displayed as code.

for a principal

Decide how much structure your packages' landing pages carry and hold it consistent, so a stranger moving between your team's packages meets the same shape rather than one author's markdown habits.

## Doc comments have a syntax, and it is much smaller than markdown A Go doc comment is prose with a handful of recognised constructs. If you write markdown, most of it is passed through as literal characters and the whole comment collapses into one block of text — the run-on paragraph symptom. Knowing the actual list takes a minute and fixes it permanently. ### Paragraphs A paragraph is a span of unindented, non-blank comment lines. Paragraphs are separated by an **empty comment line** — a line containing only `//`. Line breaks inside a paragraph do not survive: the text is reflowed. So three sentences on three consecutive `//` lines are one paragraph, not three, and that alone explains most run-on output. ### Code blocks A span of lines **indented** relative to the surrounding text (conventionally a tab after the `//`) is a **preformatted block**, rendered verbatim in a monospaced style. This is how you show a short usage snippet. It is also the second most common accident: indenting a sentence for visual emphasis turns it into code. ### Lists A list item is an indented line beginning with a bullet — a dash, star, plus or the Unicode bullet character — or with a number followed by a dot or a right parenthesis. A run of such items is a list, and a list **must be preceded by a blank comment line**; without it the items are absorbed into the paragraph above. Canonical formatting indents each item and puts the marker and a space before the text: ```go // Entries leave in two ways: // // - the lifetime expires, or // - the caller removes them. ``` List items hold a single paragraph each; nested lists are not supported. ### Headings A heading is a line that begins with a **number sign followed by a space** and then the heading text — `// # Eviction`. That is the only heading form. `##`, underlines, and `**bold**` are not recognised and appear as the characters you typed. Headings are worth using in a long package comment, where they give the rendered page a table of contents; they are noise in a three-line comment on a function. ### Links Three link forms exist: - **Doc links.** `[Name]` links to a declaration in the same package; `[pkg.Name]` links into a package imported by the same file, or you can spell the full import path; `[*pkg.Type]` handles a pointer form. If the target cannot be resolved, the brackets are shown as literal text — which is how a broken link hides in plain sight. - **Plain URLs.** A bare `https://...` in the text is turned into a link automatically. - **Link definitions.** Lines at the end of the comment shaped `// [label]: https://example.com/page` define named links used as `[label]` in the prose. They are stripped from the rendered text. ### The Deprecated paragraph One more construct is machine-read: a paragraph that begins with `Deprecated:` marks the identifier it documents as deprecated. It must be its own paragraph — preceded by an empty comment line — and conventionally goes last, after the prose that still explains what the thing does. The rest of the paragraph should say what to use instead, because that sentence is what the reader sees when tooling surfaces the notice. Documentation sites and editors both key off this exact prefix, so `DEPRECATED`, `@deprecated` or a sentence merely containing the word does nothing. ### Putting it together A package comment that reads well as a landing page typically has: one summary sentence, a short paragraph of orientation, a heading or two for the sections a stranger needs, one indented block showing the smallest working call, and doc links to the entry points. Everything there comes from the constructs above; nothing else is available, and reaching for more markdown makes the page worse rather than richer. The practical check is to read the comment the way the reader will — as rendered documentation, not as source — before you consider the change finished. A run-on paragraph, an indented sentence shown as code, or a bracketed name that stayed literal are all obvious there and invisible in a diff.

  • How do you mark an exported function deprecated so tools notice?
    Add a paragraph to its doc comment beginning with `Deprecated:` — its own paragraph, preceded by an empty comment line, conventionally last. The rest of that paragraph should name the replacement, because that is the sentence readers see when the notice is surfaced. The declaration itself stays exactly where it is; the prefix is what documentation sites and editors key on.
  • How do you link from a doc comment to a symbol in another package?
    Write `[pkg.Name]` where pkg is imported by the same file, or spell the full import path inside the brackets; `[*pkg.Type]` handles the pointer form. A bare URL in the text auto-links, and a line shaped `// [label]: https://…` at the end defines a named link. An unresolvable target is rendered as literal brackets rather than reported.
  • Why does a bulleted list sometimes get swallowed by the paragraph above it?
    Because there is no empty comment line before the first item. A list has to start a fresh block; without the separator the indented lines are treated as a continuation of the preceding paragraph and reflowed into it. The same separator rule is what makes a code block stand apart from the sentence that introduces it.

saying these in an interview costs you the question

  • Assumes full Markdown works in a Go doc comment
  • Uses ## for a subheading or ** for bold
  • Writes a list with no empty comment line before it
  • Indents prose for emphasis, turning it into a code block
  • Thinks line breaks inside a paragraph are preserved
  • Writes @deprecated or DEPRECATED instead of the Deprecated: prefix