feat: add source hyperlinks (commit SHA permalinks) to all pattern files

Every source reference now links to the exact line in the golang/go
repo at commit 17bd5ab. Added PATTERN_COMPLETE sentinels.

Total: 154 hyperlinks across 10 topic files.
This commit is contained in:
Rodin
2026-04-30 14:42:20 -07:00
parent 99c0865e93
commit c8ed244a07
9 changed files with 172 additions and 144 deletions
+14 -10
View File
@@ -1,10 +1,12 @@
# API Conventions in the Go Standard Library
**Source:** [golang/go](https://github.com/golang/go) at commit [`17bd5ab`](https://github.com/golang/go/tree/17bd5ab8c650155dd2bd09f7005726552639eea0)
## 1. The Must Pattern
**Pattern name:** MustXxx (Panic on Error)
**Source citation:** `regexp/regexp.go` lines 310320, `text/template/helper.go` lines 1930
**Source citation:** [regexp/regexp.go#L310](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/regexp/regexp.go#L310), [text/template/helper.go#L19](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/text/template/helper.go#L19)
**What it does:** A function wraps a fallible constructor and panics if the error
is non-nil. Named `MustXxx` or `Must` (when wrapping a generic `(T, error)` pair).
@@ -114,7 +116,7 @@ func Must(t *Template, err error) *Template {
**Pattern name:** Fallible Constructor + Must Wrapper
**Source citation:** `regexp/regexp.go` lines 130131, 310320
**Source citation:** [regexp/regexp.go#L130](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/regexp/regexp.go#L130), 310320
**What it does:** The real constructor returns `(*T, error)`. A parallel `Must` variant
wraps it for use in global variable initialization.
@@ -149,7 +151,7 @@ func MustCompile(str string) *Regexp {
**Pattern name:** WithContext Function Overload
**Source citation:** `net/http/request.go` lines 867869, 894930
**Source citation:** [net/http/request.go#L867](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/request.go#L867), 894930
**What it does:** Provides two function variants: `NewRequest` (uses `context.Background()`)
and `NewRequestWithContext` (accepts an explicit context). The simple version delegates
@@ -182,7 +184,7 @@ func NewRequestWithContext(ctx context.Context, method, url string, body io.Read
**Pattern name:** `*Options` Parameter — Nil Means Defaults
**Source citation:** `log/slog/text_handler.go` lines 2842, `log/slog/handler.go` lines 135175
**Source citation:** [log/slog/text_handler.go#L28](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/log/slog/text_handler.go#L28), [log/slog/handler.go#L135](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/log/slog/handler.go#L135)
**What it does:** A constructor accepts a pointer to an options struct. If the pointer
is nil, all defaults apply. The constructor internally substitutes a zero-value struct.
@@ -221,7 +223,7 @@ func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler {
**Pattern name:** Builder (Write Methods + String/Bytes Finalizer)
**Source citation:** `strings/builder.go` lines 14113
**Source citation:** [strings/builder.go#L14](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/strings/builder.go#L14)
**What it does:** A zero-value struct accumulates data via Write/WriteByte/WriteString
methods, then produces a final result via String(). The builder is not reusable after
@@ -264,7 +266,7 @@ func (b *Builder) String() string {
**Pattern name:** Convenience Wrappers over Configurable Core
**Source citation:** `os/file.go` lines 385415
**Source citation:** [os/file.go#L385](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/file.go#L385)
**What it does:** Simple functions (`Open`, `Create`) delegate to the fully configurable
`OpenFile` with pre-set flags. Users choose their level of control.
@@ -355,7 +357,7 @@ func OpenFile(name string, flag int, perm FileMode) (*File, error) {
**Pattern name:** Convenience Package Functions
**Source citation:** `net/http/client.go` line 109, implied by `http.Get`, `http.Post`
**Source citation:** [net/http/client.go#L109](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/client.go#L109), implied by `http.Get`, `http.Post`
**What it does:** Top-level functions like `http.Get(url)` call methods on the
`DefaultClient`. Users can bypass by creating their own `Client`.
@@ -384,7 +386,7 @@ var DefaultClient = &Client{}
**Pattern name:** RegisterXxx for Side-Effect Imports
**Source citation:** `crypto/crypto.go` lines 145150
**Source citation:** [crypto/crypto.go#L145](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/crypto/crypto.go#L145)
**What it does:** A `RegisterHash(h Hash, f func() hash.Hash)` function allows
algorithm implementations in sub-packages to register themselves via `init()`.
@@ -415,7 +417,7 @@ func RegisterHash(h Hash, f func() hash.Hash) {
**Pattern name:** Close vs Shutdown (Immediate vs Graceful)
**Source citation:** `net/http/server.go` lines 31713220 (Close), 3221+ (Shutdown)
**Source citation:** [net/http/server.go#L3171](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L3171) (Close), 3221+ (Shutdown)
**What it does:** Provides both `Close()` (immediate, forceful) and `Shutdown(ctx)`
(graceful, waits for in-flight requests). The context on Shutdown provides a
@@ -530,7 +532,7 @@ func (s *Server) Shutdown(ctx context.Context) error {
**Pattern name:** NewXxx Returning Channel-Bearing Struct
**Source citation:** `time/tick.go` lines 1645, `time/sleep.go` lines 89155
**Source citation:** [time/tick.go#L16](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/time/tick.go#L16), [time/sleep.go#L89](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/time/sleep.go#L89)
**What it does:** `NewTicker(d)` and `NewTimer(d)` return structs with a `C <-chan Time`
field. Consumers select on the channel to receive time events.
@@ -561,3 +563,5 @@ func NewTicker(d Duration) *Ticker {
return t
}
```
<!-- PATTERN_COMPLETE -->
+31 -29
View File
@@ -6,10 +6,10 @@ Patterns extracted from the Go standard library source code.
## 1. sync.Mutex — The Basic Lock
### Source: `src/sync/mutex.go:18-34`, `src/sync/mutex.go:42-67`
### Source: [src/sync/mutex.go#L18](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/mutex.go#L18), [src/sync/mutex.go#L42](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/mutex.go#L42)
```go
// src/sync/mutex.go:18-34
// [src/sync/mutex.go#L18](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/mutex.go#L18)
// A Mutex is a mutual exclusion lock.
// The zero value for a Mutex is an unlocked mutex.
//
@@ -19,13 +19,13 @@ type Mutex struct {
mu isync.Mutex
}
// src/sync/mutex.go:36-39
// [src/sync/mutex.go#L36](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/mutex.go#L36)
type Locker interface {
Lock()
Unlock()
}
// src/sync/mutex.go:43-46
// [src/sync/mutex.go#L43](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/mutex.go#L43)
func (m *Mutex) Lock() {
m.mu.Lock()
}
@@ -146,24 +146,24 @@ mu.Unlock()
## 2. sync.Once — Exactly-Once Initialization
### Source: `src/sync/once.go:12-36`, `src/sync/once.go:56-79`
### Source: [src/sync/once.go#L12](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/once.go#L12), [src/sync/once.go#L56](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/once.go#L56)
```go
// src/sync/once.go:12-23
// [src/sync/once.go#L12](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/once.go#L12)
type Once struct {
_ noCopy
done atomic.Bool
m Mutex
}
// src/sync/once.go:56-63
// [src/sync/once.go#L56](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/once.go#L56)
func (o *Once) Do(f func()) {
if !o.done.Load() {
o.doSlow(f)
}
}
// src/sync/once.go:65-72
// [src/sync/once.go#L65](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/once.go#L65)
func (o *Once) doSlow(f func()) {
o.m.Lock()
defer o.m.Unlock()
@@ -301,10 +301,10 @@ once.Do(func() {
## 3. sync.WaitGroup — Waiting for Goroutine Completion
### Source: `src/sync/waitgroup.go:14-43`, `src/sync/waitgroup.go:236-260`
### Source: [src/sync/waitgroup.go#L14](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/waitgroup.go#L14), [src/sync/waitgroup.go#L236](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/waitgroup.go#L236)
```go
// src/sync/waitgroup.go:14-43
// [src/sync/waitgroup.go#L14](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/waitgroup.go#L14)
// Typically, a main goroutine will start tasks by calling WaitGroup.Go
// and then wait for all tasks to complete by calling WaitGroup.Wait:
//
@@ -322,7 +322,7 @@ type WaitGroup struct {
### Go 1.25+: WaitGroup.Go
```go
// src/sync/waitgroup.go:236-260
// [src/sync/waitgroup.go#L236](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/waitgroup.go#L236)
func (wg *WaitGroup) Go(f func()) {
wg.Add(1)
go func() {
@@ -374,10 +374,10 @@ wg.Wait()
## 4. sync.Pool — Object Reuse for GC Pressure
### Source: `src/sync/pool.go:44-63`
### Source: [src/sync/pool.go#L44](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/pool.go#L44)
```go
// src/sync/pool.go:44-63
// [src/sync/pool.go#L44](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/pool.go#L44)
// Pool's purpose is to cache allocated but unused items for later reuse,
// relieving pressure on the garbage collector. That is, it makes it easy to
// build efficient, thread-safe free lists.
@@ -439,15 +439,15 @@ pool.Put(buf) // still has data from last use
## 5. Channel as Done Signal (Context Pattern)
### Source: `src/context/context.go:83-100` (Done channel), `src/io/pipe.go:42-45`
### Source: [src/context/context.go#L83](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/context/context.go#L83) (Done channel), [src/io/pipe.go#L42](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/pipe.go#L42)
```go
// src/context/context.go:83-100
// [src/context/context.go#L83](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/context/context.go#L83)
// Done returns a channel that's closed when work done on behalf of this
// context should be canceled.
Done() <-chan struct{}
// src/io/pipe.go:42-45
// [src/io/pipe.go#L42](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/pipe.go#L42)
type pipe struct {
once sync.Once
done chan struct{} // closed on pipe close
@@ -583,10 +583,10 @@ close(done)
## 6. Context Propagation Rules
### Source: `src/context/context.go:37-48`
### Source: [src/context/context.go#L37](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/context/context.go#L37)
```go
// src/context/context.go:37-48
// [src/context/context.go#L37](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/context/context.go#L37)
// Do not store Contexts inside a struct type; instead, pass a Context
// explicitly to each function that needs it. The Context should be the first
// parameter, typically named ctx:
@@ -622,10 +622,10 @@ func doWork(data Data, ctx context.Context) // wrong position
## 7. Context Cancellation with Timeout
### Source: `src/net/http/server.go:4007-4050` (TimeoutHandler)
### Source: [src/net/http/server.go#L4007](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L4007) (TimeoutHandler)
```go
// src/net/http/server.go:4011-4050
// [src/net/http/server.go#L4011](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L4011)
func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
ctx, cancelCtx := context.WithTimeout(r.Context(), h.dt)
defer cancelCtx()
@@ -675,10 +675,10 @@ func longWork(ctx context.Context) {
## 8. Select with Non-Blocking Check
### Source: `src/io/pipe.go:51-60`
### Source: [src/io/pipe.go#L51](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/pipe.go#L51)
```go
// src/io/pipe.go:51-60
// [src/io/pipe.go#L51](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/pipe.go#L51)
func (p *pipe) read(b []byte) (n int, err error) {
select {
case <-p.done:
@@ -719,17 +719,17 @@ for {
## 9. Channel Pipeline (io.Pipe)
### Source: `src/io/pipe.go:38-45`, `src/io/pipe.go:195-205`
### Source: [src/io/pipe.go#L38](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/pipe.go#L38), [src/io/pipe.go#L195](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/pipe.go#L195)
```go
// src/io/pipe.go:38-45
// [src/io/pipe.go#L38](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/pipe.go#L38)
type pipe struct {
wrCh chan []byte // writer sends data slices
rdCh chan int // reader returns bytes consumed
done chan struct{}
}
// src/io/pipe.go:195-205
// [src/io/pipe.go#L195](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/pipe.go#L195)
func Pipe() (*PipeReader, *PipeWriter) {
pw := &PipeWriter{r: PipeReader{pipe: pipe{
wrCh: make(chan []byte), // unbuffered
@@ -868,10 +868,10 @@ func produce() <-chan int {
## 10. Background Worker with Context Shutdown
### Source: `src/database/sql/sql.go:836-843`
### Source: [src/database/sql/sql.go#L836](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/database/sql/sql.go#L836)
```go
// src/database/sql/sql.go:836-843
// [src/database/sql/sql.go#L836](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/database/sql/sql.go#L836)
func OpenDB(c driver.Connector) *DB {
ctx, cancel := context.WithCancel(context.Background())
db := &DB{
@@ -903,10 +903,10 @@ go func() {
## 11. noCopy — Preventing Value Copies
### Source: `src/sync/cond.go:120-126`
### Source: [src/sync/cond.go#L120](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/cond.go#L120)
```go
// src/sync/cond.go:120-126
// [src/sync/cond.go#L120](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/cond.go#L120)
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
@@ -947,3 +947,5 @@ func doWork(wg *sync.WaitGroup) {
| Backpressure between producer/consumer | Unbuffered channels |
| Long-lived background worker | Goroutine + context cancellation |
| Prevent struct copying | Embed `noCopy` field |
<!-- PATTERN_COMPLETE -->
+13 -9
View File
@@ -1,10 +1,12 @@
# Documentation Patterns in the Go Standard Library
**Source:** [golang/go](https://github.com/golang/go) at commit [`17bd5ab`](https://github.com/golang/go/tree/17bd5ab8c650155dd2bd09f7005726552639eea0)
## 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
**Source citation:** [net/http/doc.go#L6](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/doc.go#L6), [os/file.go#L5](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/file.go#L5), [log/slog/doc.go#L6](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/log/slog/doc.go#L6)
**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
@@ -57,7 +59,7 @@ expressed as key-value pairs.
**Pattern name:** `# Heading` in Doc Comments
**Source citation:** `os/file.go` lines 3743, `net/http/doc.go` (multiple sections)
**Source citation:** [os/file.go#L37](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/file.go#L37), `net/http/doc.go` (multiple sections)
**What it does:** Uses `# Section Name` within the package doc comment to organize
long documentation into navigable sections.
@@ -84,7 +86,7 @@ too many sections (fragmenting simple docs).
**Pattern name:** `// TypeName verb...` or `// FuncName verb...`
**Source citation:** `net/http/server.go` lines 6482 (Handler), `bufio/scan.go` lines 1427 (Scanner)
**Source citation:** [net/http/server.go#L64](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L64) (Handler), [bufio/scan.go#L14](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/bufio/scan.go#L14) (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.
@@ -125,7 +127,7 @@ the comment entirely.
**Pattern name:** `[TypeName]`, `[Package.Symbol]`, `[Method]` Links
**Source citation:** `net/http/server.go` lines 6570, `os/file.go` line 9
**Source citation:** [net/http/server.go#L65](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L65), [os/file.go#L9](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/file.go#L9)
**What it does:** Doc comments use `[SymbolName]` to create hyperlinks to other
identifiers. These render as clickable links on pkg.go.dev.
@@ -158,7 +160,7 @@ over-linking (every mention of every type).
**Pattern name:** `func ExampleXxx()` / `func ExampleType_Method()`
**Source citation:** `regexp/example_test.go` lines 1328, `net/http/example_handle_test.go` lines 1631
**Source citation:** [regexp/example_test.go#L13](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/regexp/example_test.go#L13), [net/http/example_handle_test.go#L16](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/example_handle_test.go#L16)
**What it does:** Functions named `Example`, `ExampleXxx`, or `ExampleType_Method`
in `_test.go` files serve as both executable tests and documentation. They include
@@ -278,7 +280,7 @@ func ExampleHandle() {
**Pattern name:** Indented Code Blocks in Comments
**Source citation:** `os/file.go` lines 1735, `time/time.go` lines 928933
**Source citation:** [os/file.go#L17](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/file.go#L17), [time/time.go#L928](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/time/time.go#L928)
**What it does:** Doc comments include indented code snippets (4 spaces) that render
as preformatted code blocks in godoc.
@@ -318,7 +320,7 @@ for inline (use Example functions instead); examples that reference unexported s
**Pattern name:** `// Deprecated: ...` in Doc Comments
**Source citation:** `net/http/server.go` line 57 (ErrWriteAfterFlush), `os/file.go` lines 9395
**Source citation:** [net/http/server.go#L57](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L57) (ErrWriteAfterFlush), [os/file.go#L93](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/file.go#L93)
**What it does:** A paragraph starting with `Deprecated:` marks an identifier as
deprecated and explains what to use instead.
@@ -399,7 +401,7 @@ ErrWriteAfterFlush = errors.New("unused")
**Pattern name:** "If there is an error, it will be of type [*XxxError]"
**Source citation:** `os/file.go` lines 388, 406
**Source citation:** [os/file.go#L388](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/file.go#L388), 406
**What it does:** Functions document the concrete error type they return, enabling
callers to type-assert for additional context.
@@ -428,7 +430,7 @@ func Open(name string) (*File, error) {
**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
**Source citation:** [net/http/transport.go#L79](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/transport.go#L79), [os/types.go#L17](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/types.go#L17), [regexp/regexp.go#L77](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/regexp/regexp.go#L77)
**What it does:** Doc comments explicitly state the concurrency safety of a type
or note exceptions where concurrent use is not safe.
@@ -454,3 +456,5 @@ concurrent use by multiple goroutines").
// A Regexp is safe for concurrent use by multiple goroutines,
// except for configuration methods, such as [Regexp.Longest].
```
<!-- PATTERN_COMPLETE -->
+27 -25
View File
@@ -6,21 +6,21 @@ Patterns extracted from the Go standard library source code.
## 1. Sentinel Errors
### Source: `src/io/io.go:40-43` (EOF), `src/errors/errors.go:81-83` (ErrUnsupported)
### Source: [src/io/io.go#L40](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L40) (EOF), [src/errors/errors.go#L81](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/errors.go#L81) (ErrUnsupported)
```go
// src/io/io.go:40-43
// [src/io/io.go#L40](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L40)
// EOF is the error returned by Read when no more input is available.
// (Read must return EOF itself, not an error wrapping EOF,
// because callers will test for EOF using ==.)
var EOF = errors.New("EOF")
// src/io/io.go:47-49
// [src/io/io.go#L47](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L47)
var ErrUnexpectedEOF = errors.New("unexpected EOF")
```
```go
// src/errors/errors.go:81-83
// [src/errors/errors.go#L81](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/errors.go#L81)
var ErrUnsupported = New("unsupported operation")
```
@@ -132,15 +132,15 @@ func Read() error {
## 2. errors.New — Minimal Error Construction
### Source: `src/errors/errors.go:62-69`
### Source: [src/errors/errors.go#L62](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/errors.go#L62)
```go
// src/errors/errors.go:62-64
// [src/errors/errors.go#L62](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/errors.go#L62)
func New(text string) error {
return &errorString{text}
}
// src/errors/errors.go:66-69
// [src/errors/errors.go#L66](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/errors.go#L66)
type errorString struct {
s string
}
@@ -177,10 +177,10 @@ func doThing() error {
## 3. Error Wrapping with fmt.Errorf and %w
### Source: `src/fmt/errors.go:13-23`, `src/fmt/errors.go:70-80`
### Source: [src/fmt/errors.go#L13](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/fmt/errors.go#L13), [src/fmt/errors.go#L70](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/fmt/errors.go#L70)
```go
// src/fmt/errors.go:13-23
// [src/fmt/errors.go#L13](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/fmt/errors.go#L13)
// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
//
@@ -190,7 +190,7 @@ func doThing() error {
// Unwrap method returning a []error containing all the %w operands.
func Errorf(format string, a ...any) (err error) { ... }
// src/fmt/errors.go:70-80
// [src/fmt/errors.go#L70](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/fmt/errors.go#L70)
type wrapError struct {
msg string
err error
@@ -310,10 +310,10 @@ return fmt.Errorf("internal: %w", internalErr) // now callers depend on interna
## 4. errors.Is — Checking Error Identity Through Chains
### Source: `src/errors/wrap.go:30-44`
### Source: [src/errors/wrap.go#L30](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/wrap.go#L30)
```go
// src/errors/wrap.go:30-44
// [src/errors/wrap.go#L30](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/wrap.go#L30)
func Is(err, target error) bool {
if err == nil || target == nil {
return err == target
@@ -377,10 +377,10 @@ if errors.Is(err, os.ErrNotExist) { ... } // works through wrapping
## 5. errors.As — Extracting Error Types Through Chains
### Source: `src/errors/wrap.go:96-120`
### Source: [src/errors/wrap.go#L96](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/wrap.go#L96)
```go
// src/errors/wrap.go:96-120
// [src/errors/wrap.go#L96](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/wrap.go#L96)
func As(err error, target any) bool {
if err == nil {
return false
@@ -406,7 +406,7 @@ if errors.As(err, &pathErr) {
### Go 1.24+: errors.AsType (generic version)
From `src/errors/errors.go:48-56` doc:
From [src/errors/errors.go#L48](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/errors.go#L48) doc:
```go
if perr, ok := errors.AsType[*fs.PathError](err); ok {
fmt.Println(perr.Path)
@@ -428,10 +428,10 @@ if errors.As(err, &pathErr) { ... } // works through wrapping
## 6. errors.Join — Multi-Error Aggregation
### Source: `src/errors/join.go:20-39`
### Source: [src/errors/join.go#L20](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/join.go#L20)
```go
// src/errors/join.go:20-39
// [src/errors/join.go#L20](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/join.go#L20)
func Join(errs ...error) error {
n := 0
for _, err := range errs {
@@ -555,7 +555,7 @@ return lastErr
## 7. Custom Is() Method — Equivalence Classes
### Source: `src/errors/wrap.go:42-44` (doc comment), `src/context/context.go:177-179`
### Source: [src/errors/wrap.go#L42](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/wrap.go#L42) (doc comment), [src/context/context.go#L177](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/context/context.go#L177)
From the `errors.Is` doc:
```go
@@ -569,7 +569,7 @@ From the `errors.Is` doc:
Real example from context:
```go
// src/context/context.go:177-179
// [src/context/context.go#L177](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/context/context.go#L177)
type deadlineExceededError struct{}
func (deadlineExceededError) Error() string { return "context deadline exceeded" }
@@ -594,10 +594,10 @@ func (e MyError) Is(target error) bool {
## 8. Error Wrapping in Custom Types (Unwrap pattern)
### Source: `src/encoding/json/encode.go:276-293`
### Source: [src/encoding/json/encode.go#L276](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/encode.go#L276)
```go
// src/encoding/json/encode.go:276-282
// [src/encoding/json/encode.go#L276](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/encode.go#L276)
type MarshalerError struct {
Type reflect.Type
Err error
@@ -650,10 +650,10 @@ func (e *MyError) Error() string { return e.Err.Error() }
## 9. ErrUnsupported — Feature Detection via Errors
### Source: `src/errors/errors.go:76-83`
### Source: [src/errors/errors.go#L76](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/errors.go#L76)
```go
// src/errors/errors.go:76-83
// [src/errors/errors.go#L76](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/errors/errors.go#L76)
// ErrUnsupported indicates that a requested operation cannot be performed,
// because it is unsupported.
//
@@ -685,10 +685,10 @@ return errors.ErrUnsupported // no info about what operation or why
## 10. Error String Conventions
### Source: `src/net/http/server.go:39-56`
### Source: [src/net/http/server.go#L39](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L39)
```go
// src/net/http/server.go:39-56
// [src/net/http/server.go#L39](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L39)
var (
ErrHijacked = errors.New("http: connection has been hijacked")
ErrContentLength = errors.New("http: wrote more than the declared Content-Length")
@@ -742,3 +742,5 @@ Is this a specific, well-known condition?
| Aggregate multiple errors | `errors.Join(err1, err2)` |
| Make custom types traversable | Implement `Unwrap() error` |
| Define error equivalence | Implement `Is(error) bool` |
<!-- PATTERN_COMPLETE -->
+30 -28
View File
@@ -6,22 +6,22 @@ Patterns extracted from the Go standard library source code.
## 1. Small Interfaces (1-2 Methods)
### Source: `src/io/io.go:80-92` (Reader), `93-103` (Writer), `105-109` (Closer)
### Source: [src/io/io.go#L80](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L80) (Reader), `93-103` (Writer), `105-109` (Closer)
Go's most powerful interfaces have exactly **one method**:
```go
// src/io/io.go:80-92
// [src/io/io.go#L80](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L80)
type Reader interface {
Read(p []byte) (n int, err error)
}
// src/io/io.go:93-103
// [src/io/io.go#L93](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L93)
type Writer interface {
Write(p []byte) (n int, err error)
}
// src/io/io.go:105-109
// [src/io/io.go#L105](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L105)
type Closer interface {
Close() error
}
@@ -120,30 +120,30 @@ Large interfaces are hard to implement, hard to mock, and couple consumers to ca
## 2. Interface Composition
### Source: `src/io/io.go:131-155`
### Source: [src/io/io.go#L131](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L131)
Compose small interfaces into larger ones only when needed:
```go
// src/io/io.go:131-134
// [src/io/io.go#L131](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L131)
type ReadWriter interface {
Reader
Writer
}
// src/io/io.go:136-139
// [src/io/io.go#L136](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L136)
type ReadCloser interface {
Reader
Closer
}
// src/io/io.go:141-144
// [src/io/io.go#L141](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L141)
type WriteCloser interface {
Writer
Closer
}
// src/io/io.go:146-150
// [src/io/io.go#L146](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L146)
type ReadWriteCloser interface {
Reader
Writer
@@ -168,13 +168,13 @@ func processData(rw ReadWriteCloser) {
## 3. Accept Interfaces, Return Structs
### Source: `src/io/io.go:461` (LimitReader), `src/io/io.go:618` (TeeReader)
### Source: [src/io/io.go#L461](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L461) (LimitReader), [src/io/io.go#L618](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L618) (TeeReader)
```go
// src/io/io.go:461
func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} }
// src/io/io.go:467-471
// [src/io/io.go#L467](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L467)
type LimitedReader struct {
R Reader // underlying reader
N int64 // max bytes remaining
@@ -182,7 +182,7 @@ type LimitedReader struct {
```
```go
// src/io/io.go:618-620
// [src/io/io.go#L618](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L618)
func TeeReader(r Reader, w Writer) Reader {
return &teeReader{r, w}
}
@@ -272,7 +272,7 @@ func NewServer() ServerInterface // hides useful config fields
## 4. Interface Satisfaction as a Compile-Time Check
### Source: `src/io/io.go:645`, `src/net/http/server.go:4071`
### Source: [src/io/io.go#L645](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L645), [src/net/http/server.go#L4071](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L4071)
```go
// src/io/io.go:645
@@ -299,10 +299,10 @@ func doSomething(w ResponseWriter) {
## 5. Interface-Based Polymorphism (sort.Interface)
### Source: `src/sort/sort.go:16-41`
### Source: [src/sort/sort.go#L16](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sort/sort.go#L16)
```go
// src/sort/sort.go:16-41
// [src/sort/sort.go#L16](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sort/sort.go#L16)
type Interface interface {
Len() int
Less(i, j int) bool
@@ -328,17 +328,17 @@ Note: Since Go 1.21, `slices.SortFunc` is preferred for slices (generic + faster
## 6. The Adapter Pattern (HandlerFunc)
### Source: `src/net/http/server.go:2334-2342`
### Source: [src/net/http/server.go#L2334](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L2334)
```go
// src/net/http/server.go:2334-2338
// [src/net/http/server.go#L2334](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L2334)
// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)
// src/net/http/server.go:2341-2342
// [src/net/http/server.go#L2341](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L2341)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
@@ -436,15 +436,15 @@ func (h myHandler) ServeHTTP(w ResponseWriter, r *Request) {
## 7. Optional Interfaces (Runtime Feature Detection)
### Source: `src/net/http/server.go:165-175` (Flusher), `src/net/http/server.go:183-206` (Hijacker)
### Source: [src/net/http/server.go#L165](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L165) (Flusher), [src/net/http/server.go#L183](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L183) (Hijacker)
```go
// src/net/http/server.go:165-170
// [src/net/http/server.go#L165](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L165)
type Flusher interface {
Flush()
}
// src/net/http/server.go:183-206
// [src/net/http/server.go#L183](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L183)
type Hijacker interface {
Hijack() (net.Conn, *bufio.ReadWriter, error)
}
@@ -564,10 +564,10 @@ type ResponseWriter interface {
## 8. The Stringer Interface (Convention-Based Behavior)
### Source: `src/fmt/print.go:63-66`
### Source: [src/fmt/print.go#L63](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/fmt/print.go#L63)
```go
// src/fmt/print.go:63-66
// [src/fmt/print.go#L63](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/fmt/print.go#L63)
type Stringer interface {
String() string
}
@@ -596,10 +596,10 @@ func printThing(v any) string {
## 9. Interface Upgrade Pattern (WriterTo/ReaderFrom in io.Copy)
### Source: `src/io/io.go:410-417`
### Source: [src/io/io.go#L410](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L410)
```go
// src/io/io.go:410-417
// [src/io/io.go#L410](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L410)
func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {
// If the reader has a WriteTo method, use it to do the copy.
// Avoids an allocation and a copy.
@@ -632,15 +632,15 @@ func Copy(dst Writer, src Reader) {
## 10. The driver.Driver Pattern (Plugin Interfaces)
### Source: `src/database/sql/driver/driver.go:85-97`, `104-112`
### Source: [src/database/sql/driver/driver.go#L85](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/database/sql/driver/driver.go#L85), `104-112`
```go
// src/database/sql/driver/driver.go:85-97
// [src/database/sql/driver/driver.go#L85](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/database/sql/driver/driver.go#L85)
type Driver interface {
Open(name string) (Conn, error)
}
// src/database/sql/driver/driver.go:104-112
// [src/database/sql/driver/driver.go#L104](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/database/sql/driver/driver.go#L104)
type DriverContext interface {
OpenConnector(name string) (Connector, error)
}
@@ -676,3 +676,5 @@ type Driver interface {
| Compile-time interface checks | `var _ Interface = (*Type)(nil)` |
| Runtime interface upgrade for optimization | `io.Copy``WriterTo`/`ReaderFrom` |
| Plugin/driver interfaces start minimal | `database/sql/driver.Driver` |
<!-- PATTERN_COMPLETE -->
+13 -11
View File
@@ -6,10 +6,10 @@ Patterns extracted from the Go standard library source code.
## 1. Package-Level Documentation
### Source: `src/io/io.go:5-13`, `src/sync/mutex.go:5-11`, `src/context/context.go:5-57`
### Source: [src/io/io.go#L5](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L5), [src/sync/mutex.go#L5](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/mutex.go#L5), [src/context/context.go#L5](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/context/context.go#L5)
```go
// src/io/io.go:5-13
// [src/io/io.go#L5](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L5)
// Package io provides basic interfaces to I/O primitives.
// Its primary job is to wrap existing implementations of such primitives,
// such as those in package os, into shared public interfaces that
@@ -22,7 +22,7 @@ package io
```
```go
// src/sync/mutex.go:5-11
// [src/sync/mutex.go#L5](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/sync/mutex.go#L5)
// Package sync provides basic synchronization primitives such as mutual
// exclusion locks. Other than the Once and WaitGroup types, most are intended
// for use by low-level library routines. Higher-level synchronization is
@@ -222,7 +222,7 @@ type Parser struct {
## 5. init() Functions — Use Sparingly
### Source: `src/net/http/http2.go:37`
### Source: [src/net/http/http2.go#L37](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/http2.go#L37)
```go
// src/net/http/http2.go:37
@@ -379,7 +379,7 @@ srv := &http.Server{
## 7. Constructor Pattern — NewX Functions
### Source: `src/net/http/server.go:2639`, `src/database/sql/sql.go:836`
### Source: [src/net/http/server.go#L2639](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L2639), [src/database/sql/sql.go#L836](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/database/sql/sql.go#L836)
```go
// src/net/http/server.go:2639
@@ -387,7 +387,7 @@ func NewServeMux() *ServeMux {
return new(ServeMux)
}
// src/database/sql/sql.go:836-843
// [src/database/sql/sql.go#L836](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/database/sql/sql.go#L836)
func OpenDB(c driver.Connector) *DB {
ctx, cancel := context.WithCancel(context.Background())
db := &DB{
@@ -488,10 +488,10 @@ The user never sees `driver.Conn`. The driver never sees `sql.DB`'s pool logic.
## 10. Context Key Pattern — Type-Safe Context Values
### Source: `src/context/context.go:132-164`, `src/net/http/server.go:244-252`
### Source: [src/context/context.go#L132](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/context/context.go#L132), [src/net/http/server.go#L244](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L244)
```go
// src/context/context.go:132-164 (from doc)
// [src/context/context.go#L132](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/context/context.go#L132) (from doc)
// package user
//
// type key int
@@ -508,7 +508,7 @@ The user never sees `driver.Conn`. The driver never sees `sql.DB`'s pool logic.
```
```go
// src/net/http/server.go:244-252
// [src/net/http/server.go#L244](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L244)
var (
ServerContextKey = &contextKey{"http-server"}
LocalAddrContextKey = &contextKey{"local-addr"}
@@ -598,10 +598,10 @@ ctx = context.WithValue(ctx, "timeout", 5*time.Second) // use function params!
## 11. Struct Tags for Codec Configuration
### Source: `src/encoding/json/tags.go:17-21`, `src/encoding/json/encode.go:101-181`
### Source: [src/encoding/json/tags.go#L17](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/tags.go#L17), [src/encoding/json/encode.go#L101](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/encode.go#L101)
```go
// src/encoding/json/tags.go:17-21
// [src/encoding/json/tags.go#L17](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/tags.go#L17)
func parseTag(tag string) (string, tagOptions) {
tag, opt, _ := strings.Cut(tag, ",")
return tag, tagOptions(opt)
@@ -645,3 +645,5 @@ Struct tags are metadata for codecs. The `json` package reads `json:"..."` tags
| API layers | Separate user from implementor (SPI) |
| Context values | Unexported key type + typed accessors |
| Configuration | Struct literals or functional options |
<!-- PATTERN_COMPLETE -->
+13 -9
View File
@@ -1,10 +1,12 @@
# Struct Design Patterns in the Go Standard Library
**Source:** [golang/go](https://github.com/golang/go) at commit [`17bd5ab`](https://github.com/golang/go/tree/17bd5ab8c650155dd2bd09f7005726552639eea0)
## 1. Zero-Value Usability
**Pattern name:** Zero Value Ready
**Source citation:** `net/http/client.go` lines 3135, `strings/builder.go` lines 1416
**Source citation:** [net/http/client.go#L31](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/client.go#L31), [strings/builder.go#L14](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/strings/builder.go#L14)
**What it does:** Structs are designed so their zero value is immediately useful without
explicit initialization. Nil fields fall back to sensible defaults at method call time.
@@ -126,7 +128,7 @@ type Buffer struct {
**Pattern name:** Indirection via Unexported Impl
**Source citation:** `os/types.go` lines 1620, `os/file_unix.go` lines 5971
**Source citation:** [os/types.go#L16](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/types.go#L16), [os/file_unix.go#L59](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/file_unix.go#L59)
**What it does:** The exported type (`File`) embeds a pointer to an unexported type
(`*file`) that holds the real implementation state. Users interact only with the
@@ -173,7 +175,7 @@ type file struct {
**Pattern name:** NewXxx Constructor
**Source citation:** `bufio/scan.go` lines 8996, `bufio/bufio.go` lines 5060
**Source citation:** [bufio/scan.go#L89](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/bufio/scan.go#L89), [bufio/bufio.go#L50](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/bufio/bufio.go#L50)
**What it does:** A package-level function `NewXxx(deps) *Xxx` constructs the type
with required dependencies and internal defaults that can't be expressed via zero
@@ -294,7 +296,7 @@ func NewRequest(method, url string, body io.Reader) (*Request, error) {
**Pattern name:** NewXxx / NewXxxSize Pair
**Source citation:** `bufio/bufio.go` lines 50, 62, 589, 607
**Source citation:** [bufio/bufio.go#L50](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/bufio/bufio.go#L50), 62, 589, 607
**What it does:** Provides two constructors — one with defaults (`NewReader`) and one
with explicit configuration (`NewReaderSize`). The default version calls the
@@ -325,7 +327,7 @@ func NewWriter(w io.Writer) *Writer {
**Pattern name:** Configuration Struct (Exported Fields, Nil-Means-Default)
**Source citation:** `net/http/server.go` lines 30203120, `crypto/tls/common.go` lines 566+, `log/slog/handler.go` lines 135175
**Source citation:** [net/http/server.go#L3020](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L3020), [crypto/tls/common.go#L566](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/crypto/tls/common.go#L566)+, [log/slog/handler.go#L135](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/log/slog/handler.go#L135)
**What it does:** A struct with exported, documented fields provides all
configuration knobs. Nil/zero values always mean "use the default".
@@ -440,7 +442,7 @@ func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler {
**Pattern name:** Interface Abstraction for Pluggable Implementations
**Source citation:** `crypto/crypto.go` lines 180200, `net/http/transport.go` lines 6682
**Source citation:** [crypto/crypto.go#L180](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/crypto/crypto.go#L180), [net/http/transport.go#L66](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/transport.go#L66)
**What it does:** Core behavior is defined via an interface. The package provides
a default concrete implementation, but any user type satisfying the interface
@@ -485,7 +487,7 @@ type Client struct {
**Pattern name:** copyCheck (Runtime Copy Detection)
**Source citation:** `strings/builder.go` lines 2540
**Source citation:** [strings/builder.go#L25](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/strings/builder.go#L25)
**What it does:** On first mutation, the Builder records its own address. Subsequent
mutations compare the current receiver address against the recorded one. If they
@@ -517,7 +519,7 @@ func (b *Builder) copyCheck() {
**Pattern name:** Package-Level Default Instance
**Source citation:** `net/http/client.go` line 109, `net/http/transport.go` lines 4758
**Source citation:** [net/http/client.go#L109](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/client.go#L109), [net/http/transport.go#L47](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/transport.go#L47)
**What it does:** The package provides a pre-configured, ready-to-use instance as
a package-level variable. Package-level convenience functions delegate to it.
@@ -557,7 +559,7 @@ var DefaultTransport RoundTripper = &Transport{
**Pattern name:** Post-Construction Configuration via Methods
**Source citation:** `bufio/scan.go` lines 275293
**Source citation:** [bufio/scan.go#L275](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/bufio/scan.go#L275)
**What it does:** After construction with `NewScanner`, optional configuration is
applied via methods (`Split`, `Buffer`) before the first call to `Scan`.
@@ -595,3 +597,5 @@ func (s *Scanner) Split(split SplitFunc) {
s.split = split
}
```
<!-- PATTERN_COMPLETE -->
+13 -9
View File
@@ -1,5 +1,7 @@
# Code Style Patterns in the Go Standard Library
**Source:** [golang/go](https://github.com/golang/go) at commit [`17bd5ab`](https://github.com/golang/go/tree/17bd5ab8c650155dd2bd09f7005726552639eea0)
## 1. Naming Conventions: mixedCaps (No Underscores)
**Pattern name:** mixedCaps / MixedCaps
@@ -34,7 +36,7 @@ const shutdownPollIntervalMax = 500 * time.Millisecond
**Pattern name:** Acronym Capitalization
**Source citation:** `net/http/request.go` line 130 (`URL`), `net/http/server.go` line 3041 (`TLSConfig`), `encoding/json/stream.go` line 280 (`JSON`)
**Source citation:** [net/http/request.go#L130](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/request.go#L130) (`URL`), [net/http/server.go#L3041](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L3041) (`TLSConfig`), [encoding/json/stream.go#L280](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/stream.go#L280) (`JSON`)
**What it does:** Acronyms and initialisms (URL, HTTP, ID, JSON, XML, HTML, TLS, TCP)
are always fully capitalized when exported, and fully lowercased when unexported.
@@ -101,7 +103,7 @@ pattern.go — URL pattern matching (ServeMux routing)
**Pattern name:** `var _ Interface = (*Type)(nil)`
**Source citation:** `io/io.go` line 645, `os/file.go` lines 747750, `encoding/json/stream.go` lines 280281
**Source citation:** [io/io.go#L645](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L645), [os/file.go#L747](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/file.go#L747), [encoding/json/stream.go#L280](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/stream.go#L280)
**What it does:** A package-level `var _ InterfaceName = (*ConcreteType)(nil)` declares
that the concrete type must satisfy the interface. The compiler verifies this at
@@ -193,7 +195,7 @@ var _ Pusher = (*timeoutWriter)(nil)
**Pattern name:** Named Returns for Documentation (and Defer)
**Source citation:** `io/io.go` lines 87, 100, 314, 387; `os/file.go` lines 140, 175
**Source citation:** [io/io.go#L87](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/io/io.go#L87), 100, 314, 387; [os/file.go#L140](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/file.go#L140), 175
**What it does:** Return values are given names when the names add documentary value
(clarifying which int is what) or when `defer` needs to modify the return value.
@@ -239,7 +241,7 @@ func (f *File) Read(b []byte) (n int, err error) {
**Pattern name:** `defer mu.Unlock()` / `defer f.Close()`
**Source citation:** `net/http/server.go` lines 31733174, `net/http/example_handle_test.go` lines 2122
**Source citation:** [net/http/server.go#L3173](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L3173), [net/http/example_handle_test.go#L21](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/example_handle_test.go#L21)
**What it does:** Resources acquired at the top of a scope are immediately deferred
for cleanup. Mutexes are locked then immediately `defer Unlock()`'d.
@@ -277,7 +279,7 @@ func (h *countHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
**Pattern name:** Sentinel Errors + Structured Error Types
**Source citation:** `os/error.go` lines 1427, `os/error.go` lines 4667
**Source citation:** [os/error.go#L14](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/error.go#L14), [os/error.go#L46](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/os/error.go#L46)
**What it does:** Package-level sentinel errors (`ErrNotExist`, `ErrPermission`) are
declared as `var` for use with `errors.Is()`. Structured error types (`*PathError`,
@@ -357,7 +359,7 @@ func (f *File) Name() string { ... }
**Pattern name:** Typed Constants with iota
**Source citation:** `crypto/crypto.go` lines 7085, `time/time.go` lines 936943
**Source citation:** [crypto/crypto.go#L70](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/crypto/crypto.go#L70), [time/time.go#L936](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/time/time.go#L936)
**What it does:** Related constants are grouped in a `const ( ... )` block using
a named type and `iota` for sequential values. Constants of the same type
@@ -463,7 +465,7 @@ const (
**Pattern name:** `// guards x` Field Comments
**Source citation:** `net/http/example_handle_test.go` line 16
**Source citation:** [net/http/example_handle_test.go#L16](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/example_handle_test.go#L16)
**What it does:** When a sync primitive (mutex) protects specific fields, a brief
comment documents what it guards: `mu sync.Mutex // guards n`.
@@ -490,7 +492,7 @@ type countHandler struct {
**Pattern name:** Named Type for Semantic Units
**Source citation:** `time/time.go` lines 915943
**Source citation:** [time/time.go#L915](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/time/time.go#L915)
**What it does:** `Duration` is `type Duration int64` — a named type over a primitive.
This gives it its own method set (`String()`, `Hours()`, `Truncate()`) and prevents
@@ -611,7 +613,7 @@ checking in code that `gofmt` would modify.
**Pattern name:** Grouped Imports (stdlib / external / internal)
**Source citation:** `net/http/server.go` lines 836
**Source citation:** [net/http/server.go#L8](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/server.go#L8)
**What it does:** Imports are organized in groups separated by blank lines:
1. Standard library
@@ -641,3 +643,5 @@ import (
"golang.org/x/net/http/httpguts"
)
```
<!-- PATTERN_COMPLETE -->
+18 -14
View File
@@ -1,5 +1,7 @@
# Advanced Go Testing Patterns
**Source:** [golang/go](https://github.com/golang/go) at commit [`17bd5ab`](https://github.com/golang/go/tree/17bd5ab8c650155dd2bd09f7005726552639eea0)
Patterns extracted from the Go standard library (`src/net/http/`, `src/encoding/json/`, `src/testing/`) and Kubernetes source code.
---
@@ -10,7 +12,7 @@ The canonical Go test style. Every Go stdlib test file uses this pattern.
### Pattern Name: Anonymous Struct Test Table
**Source:** `/tmp/go-src/src/net/http/header_test.go` lines 17-108
**Source:** [src/net/http/header_test.go#L17](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/header_test.go#L17)
**What they do:** Define test cases as a slice of anonymous structs, iterate with a range loop.
@@ -145,7 +147,7 @@ func TestHeaderWrite(t *testing.T) {
### Pattern Name: Named Table Tests with t.Run (Subtests)
**Source:** `/tmp/go-src/src/encoding/json/encode_test.go` lines 285-320, `/tmp/go-src/src/encoding/json/scanner_test.go` lines 30-50
**Source:** [src/encoding/json/encode_test.go#L285](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/encode_test.go#L285), [src/encoding/json/scanner_test.go#L30](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/scanner_test.go#L30)
**What they do:** Combine table-driven tests with `t.Run` for named subtests. Use a `CaseName` struct that captures file/line for error reporting.
@@ -180,7 +182,7 @@ func TestValid(t *testing.T) {
### Pattern Name: CaseName with Caller Position Tracking
**Source:** `/tmp/go-src/src/encoding/json/internal/jsontest/testcase.go` lines 18-37
**Source:** [src/encoding/json/internal/jsontest/testcase.go#L18](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/internal/jsontest/testcase.go#L18)
**What they do:** Create a helper type that captures the caller's file:line at the point of test case declaration, so error messages point back to the exact test case definition.
@@ -214,7 +216,7 @@ func (pos CasePos) String() string {
### Pattern Name: t.Helper() for Clean Stack Traces
**Source:** `/tmp/go-src/src/testing/testing.go` lines 1415-1435
**Source:** [src/testing/testing.go#L1415](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/testing/testing.go#L1415)
**What they do:** Call `t.Helper()` as the first line in any test utility function. This marks the function as a helper, so test failure messages report the caller's line instead of the helper's line.
@@ -254,7 +256,7 @@ func run[T TBRun[T]](t T, f func(t T, mode testMode), opts ...any) {
### Pattern Name: *testing.T as First Argument to Helpers
**Source:** `/tmp/go-src/src/net/http/serve_test.go` lines 4555-4580
**Source:** [src/net/http/serve_test.go#L4555](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/serve_test.go#L4555)
**What they do:** Pass `*testing.T` (or `testing.TB`) as the first argument to test helper functions, making the dependency on the test context explicit.
@@ -288,7 +290,7 @@ mustGet := func(url string, headers ...string) {
### Pattern Name: t.Cleanup for Test-Scoped Resources
**Source:** `/tmp/go-src/src/testing/testing.go` lines 1439-1468, `/tmp/go-src/src/net/http/clientserver_test.go` lines 120-127
**Source:** [src/testing/testing.go#L1439](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/testing/testing.go#L1439), [src/net/http/clientserver_test.go#L120](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/clientserver_test.go#L120)
**What they do:** Use `t.Cleanup(fn)` instead of `defer` for resource cleanup in tests.
@@ -348,7 +350,7 @@ ServeFile(w, r, "testdata/file")
### Pattern Name: Golden Files with -update Flag
**Source:** `/tmp/go-src/src/cmd/gofmt/gofmt_test.go` lines 18, 113-138
**Source:** [src/cmd/gofmt/gofmt_test.go#L18](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/cmd/gofmt/gofmt_test.go#L18), 113-138
**What they do:** Compare test output against `.golden` files. Provide a `-update` flag that regenerates golden files from current output when behavior intentionally changes.
@@ -488,7 +490,7 @@ func TestRewrite(t *testing.T) {
### Pattern Name: httptest.NewRecorder for Unit-Testing Handlers
**Source:** `/tmp/go-src/src/net/http/serve_test.go` lines 387-393
**Source:** [src/net/http/serve_test.go#L387](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/serve_test.go#L387)
**What they do:** Use `httptest.NewRecorder()` to test HTTP handlers without starting a server. Captures status code, headers, and body.
@@ -591,7 +593,7 @@ func TestServeMuxHandler(t *testing.T) {
### Pattern Name: httptest.NewServer for Integration-Style Tests
**Source:** `/tmp/go-src/src/net/http/clientserver_test.go` lines 203-280
**Source:** [src/net/http/clientserver_test.go#L203](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/clientserver_test.go#L203)
**What they do:** Use `httptest.NewServer` / `httptest.NewUnstartedServer` for end-to-end HTTP testing with a real TCP listener on localhost.
@@ -622,7 +624,7 @@ func newClientServerTest(t testing.TB, mode testMode, h Handler, opts ...any) *c
### Pattern Name: b.ReportAllocs + b.RunParallel + b.SetBytes
**Source:** `/tmp/go-src/src/encoding/json/bench_test.go` lines 85-101
**Source:** [src/encoding/json/bench_test.go#L85](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/encoding/json/bench_test.go#L85)
**What they do:** Combine `b.ReportAllocs()` for allocation reporting, `b.RunParallel` for concurrent benchmarks, and `b.SetBytes` for throughput metrics.
@@ -660,7 +662,7 @@ func BenchmarkCodeEncoder(b *testing.B) {
### Pattern Name: testing.Short() for Expensive Tests
**Source:** `/tmp/go-src/src/net/http/serve_test.go` lines 800, 1000, 2212, 2581
**Source:** [src/net/http/serve_test.go#L800](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/serve_test.go#L800), 1000, 2212, 2581
**What they do:** Skip slow/flaky/network-dependent tests with `testing.Short()`. The Go CI runs with `-short` in fast mode, full tests in thorough mode.
@@ -754,7 +756,7 @@ func afterTest(t testing.TB) {
### Pattern Name: Bridge File for Internal Testing
**Source:** `/tmp/go-src/src/net/http/export_test.go` lines 1-50
**Source:** [src/net/http/export_test.go#L1](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/export_test.go#L1)
**What they do:** Create an `export_test.go` file in the package itself (package `http`, not `http_test`) that exports internal symbols to external test packages. Only compiled during testing.
@@ -779,7 +781,7 @@ var (
### Pattern Name: Generic Test Runner Across Protocol Modes
**Source:** `/tmp/go-src/src/net/http/clientserver_test.go` lines 100-134
**Source:** [src/net/http/clientserver_test.go#L100](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/clientserver_test.go#L100)
**What they do:** A generic `run[T]` function that executes every client/server test in HTTP/1.1, HTTP/2, and HTTP/3 modes automatically. Tests opt into specific modes via options.
@@ -810,7 +812,7 @@ func run[T TBRun[T]](t T, f func(t T, mode testMode), opts ...any) {
### Pattern Name: io.Writer Adapter for *testing.T
**Source:** `/tmp/go-src/src/net/http/clientserver_test.go` lines 337-345
**Source:** [src/net/http/clientserver_test.go#L337](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/clientserver_test.go#L337)
**What they do:** Implement `io.Writer` backed by `t.Logf`, so server error logs appear in test output (visible with `-v`, suppressed otherwise).
@@ -830,3 +832,5 @@ func (w testLogWriter) Write(b []byte) (int, error) {
// Usage:
cst.ts.Config.ErrorLog = log.New(testLogWriter{t}, "", 0)
```
<!-- PATTERN_COMPLETE -->