| name | document-go-apis |
| description | Standard-library-style Go API documentation and comment conventions (TR-F024). Use when adding or changing exported Go identifiers, writing package comments, or backfilling godoc on a package so it reads like the Go standard library. |
Skill: Document Go APIs (standard-library style)
Feature ID: TR-F024 | Milestone: M4 (M4.11 / M4.12)
When to use
- Adding or changing any exported Go identifier (func, type, method, const, var).
- Writing or updating a package comment (
doc.go).
- Backfilling godoc on an existing package so it reads like the standard library.
The goal: a reader using go doc ./... or pkg.go.dev should understand the API
without reading the implementation. Optimize for information value, not coverage theater.
Pre-research
go doc ./internal/radiusd # see how a package currently documents
view internal/radiusd/coa_service.go # a well-documented reference in this repo
grep -rn "^// Package " internal pkg # find existing package comments
Mirror the nearest well-documented neighbor; do not invent a new comment style.
Core conventions (godoc / stdlib)
- Every exported identifier has a doc comment, and the comment starts with the identifier name:
type CoAService struct { ... }
func (s *CoAService) Disconnect(ctx context.Context, ...) (*CoAResult, error) { ... }
- Package comment: each non-
main package has exactly one package comment, in a dedicated
doc.go when it is more than a line. Start with // Package <name> ...:
package radiusd
- Full sentences, present tense, ending with a period. First sentence is a self-contained
summary (it is what pkg.go.dev shows in lists). Keep the summary on the first line.
- Document the contract, not the mechanics: parameters' meaning, return values, the zero value
if it is usable, units (e.g. Kbps vs Mbps), ownership, and what counts as success vs failure.
- Errors: state what error types / sentinel values callers should branch on
(e.g.
AuthError with a metrics tag). Wrap with %w and say so when relevant.
- Concurrency: explicitly state whether a type/func is safe for concurrent use
("safe for concurrent use by multiple goroutines" or "not safe for concurrent use").
- Context & blocking: note when a function blocks, honors
ctx cancellation, performs I/O,
or has timeout/retry semantics.
- Runnable examples for non-trivial APIs: add
Example<Name> functions in *_test.go
(package <pkg>_test); they are compiled and run by go test and rendered on pkg.go.dev.
- Deprecation: use a
// Deprecated: use X instead. paragraph; do not delete the symbol abruptly.
- Unexported code: comment only where the why is non-obvious (protocol quirks, vendor unit
conversions, security-sensitive branches). Do not narrate obvious code.
Anti-patterns (reject these)
// GetUser gets the user. — restates the name, zero information. Say what it loads, from where,
and the failure mode.
- Comment that does not start with the identifier name (breaks godoc association).
- Per-line narration of self-evident statements.
- Documenting unexported helpers exhaustively while exported API stays bare.
How to check
go doc ./internal/<pkg>
gofmt -l .
go vet ./...
go test ./...
golangci-lint run
Lint enforcement (incremental, M4.12): .golangci.yml currently disables the godoc checks
(staticcheck ST1000 package-comment, ST1020/ST1021 func/type comment format). Do not
flip them on globally in one shot — that would flag the whole tree. Backfill a package's docs first,
then enable the relevant check (or revive's exported rule) scoped to that package, so the gate
ratchets forward without a giant noisy diff.
Acceptance