Files
go-patterns/patterns/documentation.md
T
Rodin 0f1d7e4c06 feat: initial Go patterns guide from stdlib + Kubernetes source study
9 pattern files covering stdlib (structs, interfaces, API conventions, docs, style),
Kubernetes (controller/reconciler, informer/cache, leader election, code generation),
comparison (stdlib vs K8s approaches), and anti-patterns.

All patterns cite exact source files and line numbers.
2026-04-30 06:34:02 +00:00

343 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Documentation Patterns in the Go Standard Library
## 1. Package Documentation (doc.go or Package Comment)
**Pattern name:** Package Doc Comment
**Source citation:** `net/http/doc.go` lines 630, `os/file.go` lines 543, `log/slog/doc.go` lines 630
**What it does:** The first file in a package (by convention `doc.go`, or the main
source file) starts with a `// Package xxx ...` comment that explains the package's
purpose, key types, and typical usage patterns.
**Why:** This is the first thing users see in `go doc <pkg>` and on pkg.go.dev. It
sets context, teaches the mental model, and provides copy-paste examples.
**Anti-pattern:** No package comment; package comment that just restates the package
name ("Package http provides http"); putting documentation in README instead of code.
**Code examples from source:**
```go
// net/http/doc.go:6-12
/*
Package http provides HTTP client and server implementations.
[Get], [Head], [Post], and [PostForm] make HTTP (or HTTPS) requests:
resp, err := http.Get("http://example.com/")
...
*/
```
```go
// os/file.go:5-43
// Package os provides a platform-independent interface to operating system
// functionality. The design is Unix-like, although the error handling is
// Go-like; failing calls return values of type error rather than error numbers.
// Often, more information is available within the error. For example,
// if a call that takes a file name fails, such as [Open] or [Stat], the error
// will include the failing file name when printed and will be of type
// [*PathError], which may be unpacked for more information.
```
```go
// log/slog/doc.go:6-10
/*
Package slog provides structured logging,
in which log records include a message,
a severity level, and various other attributes
expressed as key-value pairs.
*/
```
---
## 2. Section Headers in Package Docs
**Pattern name:** `# Heading` in Doc Comments
**Source citation:** `os/file.go` lines 3743, `net/http/doc.go` (multiple sections)
**What it does:** Uses `# Section Name` within the package doc comment to organize
long documentation into navigable sections.
**Why:** Large packages need structure. Section headers render as links in pkg.go.dev
and provide a scannable table of contents.
**Anti-pattern:** Wall-of-text package docs; using `===` or `---` (not recognized);
too many sections (fragmenting simple docs).
**Code example from source:**
```go
// os/file.go:37
// # Concurrency
//
// The methods of [File] correspond to file system operations. All are
// safe for concurrent use.
```
---
## 3. Type/Function Comment Convention
**Pattern name:** `// TypeName verb...` or `// FuncName verb...`
**Source citation:** `net/http/server.go` lines 6482 (Handler), `bufio/scan.go` lines 1427 (Scanner)
**What it does:** Every exported identifier's doc comment starts with the identifier
name, followed by a verb phrase describing what it does or represents.
**Why:** `go doc` extracts the first sentence as a summary. Starting with the name
ensures it reads correctly in both isolation (summary lists) and full context.
This is enforced by convention and checked by linters.
**Anti-pattern:** Starting with "This function..." or "The Foo type..."; starting
with articles ("A Handler is...") for functions (acceptable for types); omitting
the comment entirely.
**Code examples from source:**
```go
// net/http/server.go:64
// A Handler responds to an HTTP request.
// bufio/scan.go:14-17
// Scanner provides a convenient interface for reading data such as
// a file of newline-delimited lines of text.
// net/http/request.go:867
// NewRequest wraps NewRequestWithContext using context.Background.
// os/file.go:389-390
// Open opens the named file for reading.
// regexp/regexp.go:310-312
// MustCompile is like [Compile] but panics if the expression cannot be parsed.
// It simplifies safe initialization of global variables holding compiled regular
// expressions.
```
---
## 4. Doc Links (Square Bracket References)
**Pattern name:** `[TypeName]`, `[Package.Symbol]`, `[Method]` Links
**Source citation:** `net/http/server.go` lines 6570, `os/file.go` line 9
**What it does:** Doc comments use `[SymbolName]` to create hyperlinks to other
identifiers. These render as clickable links on pkg.go.dev.
**Why:** Cross-references help users navigate the API. Links are concise and
don't clutter the plain-text rendering.
**Anti-pattern:** Using full URLs to godoc pages; not linking related types;
over-linking (every mention of every type).
**Code examples from source:**
```go
// net/http/server.go:65-70
// [Handler.ServeHTTP] should write reply headers and data to the [ResponseWriter]
// and then return. Returning signals that the request is finished; it
// is not valid to use the [ResponseWriter] or read from the
// [Request.Body] after or concurrently with the completion of the
// ServeHTTP call.
// os/file.go:9-11
// if a call that takes a file name fails, such as [Open] or [Stat], the error
// will include the failing file name when printed and will be of type
// [*PathError], which may be unpacked for more information.
```
---
## 5. Example Test Functions
**Pattern name:** `func ExampleXxx()` / `func ExampleType_Method()`
**Source citation:** `regexp/example_test.go` lines 1328, `net/http/example_handle_test.go` lines 1631
**What it does:** Functions named `Example`, `ExampleXxx`, or `ExampleType_Method`
in `_test.go` files serve as both executable tests and documentation. They include
an `// Output:` comment that `go test` verifies.
**Why:** Examples that compile, run, and are verified can never go stale. They appear
in `go doc` and pkg.go.dev alongside the relevant symbol. They teach by showing
real, working code.
**Anti-pattern:** Examples that don't compile; examples without Output comments
(not verified); examples in README that drift from reality.
**Code examples from source:**
```go
// regexp/example_test.go:13-28
func Example() {
// Compile the expression once, usually at init time.
// Use raw strings to avoid having to quote the backslashes.
var validID = regexp.MustCompile(`^[a-z]+\[[0-9]+\]$`)
fmt.Println(validID.MatchString("adam[23]"))
fmt.Println(validID.MatchString("eve[7]"))
fmt.Println(validID.MatchString("Job[48]"))
fmt.Println(validID.MatchString("snakey"))
// Output:
// true
// true
// false
// false
}
```
```go
// net/http/example_handle_test.go:16-31
type countHandler struct {
mu sync.Mutex // guards n
n int
}
func (h *countHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.mu.Lock()
defer h.mu.Unlock()
h.n++
fmt.Fprintf(w, "count is %d\n", h.n)
}
func ExampleHandle() {
http.Handle("/count", new(countHandler))
log.Fatal(http.ListenAndServe(":8080", nil))
}
```
---
## 6. Inline Code Examples in Doc Comments
**Pattern name:** Indented Code Blocks in Comments
**Source citation:** `os/file.go` lines 1735, `time/time.go` lines 928933
**What it does:** Doc comments include indented code snippets (4 spaces) that render
as preformatted code blocks in godoc.
**Why:** Shows typical usage patterns directly in the doc comment without requiring
a separate Example test function. Good for short, illustrative snippets.
**Anti-pattern:** Non-indented code that doesn't render as code; examples too long
for inline (use Example functions instead); examples that reference unexported symbols.
**Code examples from source:**
```go
// os/file.go:17-21
// Here is a simple example, opening a file and reading some of it.
//
// file, err := os.Open("file.go") // For read access.
// if err != nil {
// log.Fatal(err)
// }
// time/time.go:928-933
// To count the number of units in a [Duration], divide:
//
// second := time.Second
// fmt.Print(int64(second/time.Millisecond)) // prints 1000
//
// To convert an integer number of units to a Duration, multiply:
//
// seconds := 10
// fmt.Print(time.Duration(seconds)*time.Second) // prints 10s
```
---
## 7. Deprecated Annotations
**Pattern name:** `// Deprecated: ...` in Doc Comments
**Source citation:** `net/http/server.go` line 57 (ErrWriteAfterFlush), `os/file.go` lines 9395
**What it does:** A paragraph starting with `Deprecated:` marks an identifier as
deprecated and explains what to use instead.
**Why:** Recognized by tooling (go vet, staticcheck, IDEs). Provides a migration
path without breaking backward compatibility.
**Anti-pattern:** Removing deprecated APIs (breaks semver); deprecating without
suggesting an alternative; using non-standard deprecation markers.
**Code example from source:**
```go
// net/http/server.go:55-57
// Deprecated: ErrWriteAfterFlush is no longer returned by
// anything in the net/http package. Callers should not
// compare errors against this variable.
ErrWriteAfterFlush = errors.New("unused")
```
---
## 8. Error Documentation Convention
**Pattern name:** "If there is an error, it will be of type [*XxxError]"
**Source citation:** `os/file.go` lines 388, 406
**What it does:** Functions document the concrete error type they return, enabling
callers to type-assert for additional context.
**Why:** Go's error handling relies on type assertions and `errors.Is/As`. Knowing
the concrete type lets callers extract structured information (path, operation,
underlying cause).
**Anti-pattern:** Returning opaque errors with no documented structure; returning
different error types from the same function without documenting which.
**Code example from source:**
```go
// os/file.go:388-390
// Open opens the named file for reading. If successful, methods on
// the returned file can be used for reading; the associated file
// descriptor has mode [O_RDONLY].
// If there is an error, it will be of type [*PathError].
func Open(name string) (*File, error) {
```
---
## 9. Concurrency Documentation
**Pattern name:** "Safe for concurrent use" / Concurrency Guarantees
**Source citation:** `net/http/transport.go` lines 7980, `os/types.go` line 17, `regexp/regexp.go` lines 7779
**What it does:** Doc comments explicitly state the concurrency safety of a type
or note exceptions where concurrent use is not safe.
**Why:** Go programs are inherently concurrent. Without explicit documentation,
users must guess whether a type needs external synchronization.
**Anti-pattern:** Leaving concurrency safety undocumented; documenting it
inconsistently across methods; saying "thread-safe" (Java-ism, use "safe for
concurrent use by multiple goroutines").
**Code examples from source:**
```go
// net/http/transport.go:79-80
// Transports should be reused instead of created as needed.
// Transports are safe for concurrent use by multiple goroutines.
// os/types.go:17
// The methods of File are safe for concurrent use.
// regexp/regexp.go:77-79
// A Regexp is safe for concurrent use by multiple goroutines,
// except for configuration methods, such as [Regexp.Longest].
```