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:
+14
-10
@@ -1,10 +1,12 @@
|
|||||||
# API Conventions in the Go Standard Library
|
# 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
|
## 1. The Must Pattern
|
||||||
|
|
||||||
**Pattern name:** MustXxx (Panic on Error)
|
**Pattern name:** MustXxx (Panic on Error)
|
||||||
|
|
||||||
**Source citation:** `regexp/regexp.go` lines 310–320, `text/template/helper.go` lines 19–30
|
**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
|
**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).
|
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
|
**Pattern name:** Fallible Constructor + Must Wrapper
|
||||||
|
|
||||||
**Source citation:** `regexp/regexp.go` lines 130–131, 310–320
|
**Source citation:** [regexp/regexp.go#L130](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/regexp/regexp.go#L130), 310–320
|
||||||
|
|
||||||
**What it does:** The real constructor returns `(*T, error)`. A parallel `Must` variant
|
**What it does:** The real constructor returns `(*T, error)`. A parallel `Must` variant
|
||||||
wraps it for use in global variable initialization.
|
wraps it for use in global variable initialization.
|
||||||
@@ -149,7 +151,7 @@ func MustCompile(str string) *Regexp {
|
|||||||
|
|
||||||
**Pattern name:** WithContext Function Overload
|
**Pattern name:** WithContext Function Overload
|
||||||
|
|
||||||
**Source citation:** `net/http/request.go` lines 867–869, 894–930
|
**Source citation:** [net/http/request.go#L867](https://github.com/golang/go/blob/17bd5ab8c650155dd2bd09f7005726552639eea0/src/net/http/request.go#L867), 894–930
|
||||||
|
|
||||||
**What it does:** Provides two function variants: `NewRequest` (uses `context.Background()`)
|
**What it does:** Provides two function variants: `NewRequest` (uses `context.Background()`)
|
||||||
and `NewRequestWithContext` (accepts an explicit context). The simple version delegates
|
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
|
**Pattern name:** `*Options` Parameter — Nil Means Defaults
|
||||||
|
|
||||||
**Source citation:** `log/slog/text_handler.go` lines 28–42, `log/slog/handler.go` lines 135–175
|
**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
|
**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.
|
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)
|
**Pattern name:** Builder (Write Methods + String/Bytes Finalizer)
|
||||||
|
|
||||||
**Source citation:** `strings/builder.go` lines 14–113
|
**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
|
**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
|
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
|
**Pattern name:** Convenience Wrappers over Configurable Core
|
||||||
|
|
||||||
**Source citation:** `os/file.go` lines 385–415
|
**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
|
**What it does:** Simple functions (`Open`, `Create`) delegate to the fully configurable
|
||||||
`OpenFile` with pre-set flags. Users choose their level of control.
|
`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
|
**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
|
**What it does:** Top-level functions like `http.Get(url)` call methods on the
|
||||||
`DefaultClient`. Users can bypass by creating their own `Client`.
|
`DefaultClient`. Users can bypass by creating their own `Client`.
|
||||||
@@ -384,7 +386,7 @@ var DefaultClient = &Client{}
|
|||||||
|
|
||||||
**Pattern name:** RegisterXxx for Side-Effect Imports
|
**Pattern name:** RegisterXxx for Side-Effect Imports
|
||||||
|
|
||||||
**Source citation:** `crypto/crypto.go` lines 145–150
|
**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
|
**What it does:** A `RegisterHash(h Hash, f func() hash.Hash)` function allows
|
||||||
algorithm implementations in sub-packages to register themselves via `init()`.
|
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)
|
**Pattern name:** Close vs Shutdown (Immediate vs Graceful)
|
||||||
|
|
||||||
**Source citation:** `net/http/server.go` lines 3171–3220 (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)`
|
**What it does:** Provides both `Close()` (immediate, forceful) and `Shutdown(ctx)`
|
||||||
(graceful, waits for in-flight requests). The context on Shutdown provides a
|
(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
|
**Pattern name:** NewXxx Returning Channel-Bearing Struct
|
||||||
|
|
||||||
**Source citation:** `time/tick.go` lines 16–45, `time/sleep.go` lines 89–155
|
**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`
|
**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.
|
field. Consumers select on the channel to receive time events.
|
||||||
@@ -561,3 +563,5 @@ func NewTicker(d Duration) *Ticker {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- PATTERN_COMPLETE -->
|
||||||
|
|||||||
+31
-29
@@ -6,10 +6,10 @@ Patterns extracted from the Go standard library source code.
|
|||||||
|
|
||||||
## 1. sync.Mutex — The Basic Lock
|
## 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
|
```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.
|
// A Mutex is a mutual exclusion lock.
|
||||||
// The zero value for a Mutex is an unlocked mutex.
|
// The zero value for a Mutex is an unlocked mutex.
|
||||||
//
|
//
|
||||||
@@ -19,13 +19,13 @@ type Mutex struct {
|
|||||||
mu isync.Mutex
|
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 {
|
type Locker interface {
|
||||||
Lock()
|
Lock()
|
||||||
Unlock()
|
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() {
|
func (m *Mutex) Lock() {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
}
|
}
|
||||||
@@ -146,24 +146,24 @@ mu.Unlock()
|
|||||||
|
|
||||||
## 2. sync.Once — Exactly-Once Initialization
|
## 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
|
```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 {
|
type Once struct {
|
||||||
_ noCopy
|
_ noCopy
|
||||||
done atomic.Bool
|
done atomic.Bool
|
||||||
m Mutex
|
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()) {
|
func (o *Once) Do(f func()) {
|
||||||
if !o.done.Load() {
|
if !o.done.Load() {
|
||||||
o.doSlow(f)
|
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()) {
|
func (o *Once) doSlow(f func()) {
|
||||||
o.m.Lock()
|
o.m.Lock()
|
||||||
defer o.m.Unlock()
|
defer o.m.Unlock()
|
||||||
@@ -301,10 +301,10 @@ once.Do(func() {
|
|||||||
|
|
||||||
## 3. sync.WaitGroup — Waiting for Goroutine Completion
|
## 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
|
```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
|
// Typically, a main goroutine will start tasks by calling WaitGroup.Go
|
||||||
// and then wait for all tasks to complete by calling WaitGroup.Wait:
|
// 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 1.25+: WaitGroup.Go
|
||||||
|
|
||||||
```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()) {
|
func (wg *WaitGroup) Go(f func()) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
@@ -374,10 +374,10 @@ wg.Wait()
|
|||||||
|
|
||||||
## 4. sync.Pool — Object Reuse for GC Pressure
|
## 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
|
```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,
|
// 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
|
// relieving pressure on the garbage collector. That is, it makes it easy to
|
||||||
// build efficient, thread-safe free lists.
|
// 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)
|
## 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
|
```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
|
// Done returns a channel that's closed when work done on behalf of this
|
||||||
// context should be canceled.
|
// context should be canceled.
|
||||||
Done() <-chan struct{}
|
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 {
|
type pipe struct {
|
||||||
once sync.Once
|
once sync.Once
|
||||||
done chan struct{} // closed on pipe close
|
done chan struct{} // closed on pipe close
|
||||||
@@ -583,10 +583,10 @@ close(done)
|
|||||||
|
|
||||||
## 6. Context Propagation Rules
|
## 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
|
```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
|
// 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
|
// explicitly to each function that needs it. The Context should be the first
|
||||||
// parameter, typically named ctx:
|
// parameter, typically named ctx:
|
||||||
@@ -622,10 +622,10 @@ func doWork(data Data, ctx context.Context) // wrong position
|
|||||||
|
|
||||||
## 7. Context Cancellation with Timeout
|
## 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
|
```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) {
|
func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
|
||||||
ctx, cancelCtx := context.WithTimeout(r.Context(), h.dt)
|
ctx, cancelCtx := context.WithTimeout(r.Context(), h.dt)
|
||||||
defer cancelCtx()
|
defer cancelCtx()
|
||||||
@@ -675,10 +675,10 @@ func longWork(ctx context.Context) {
|
|||||||
|
|
||||||
## 8. Select with Non-Blocking Check
|
## 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
|
```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) {
|
func (p *pipe) read(b []byte) (n int, err error) {
|
||||||
select {
|
select {
|
||||||
case <-p.done:
|
case <-p.done:
|
||||||
@@ -719,17 +719,17 @@ for {
|
|||||||
|
|
||||||
## 9. Channel Pipeline (io.Pipe)
|
## 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
|
```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 {
|
type pipe struct {
|
||||||
wrCh chan []byte // writer sends data slices
|
wrCh chan []byte // writer sends data slices
|
||||||
rdCh chan int // reader returns bytes consumed
|
rdCh chan int // reader returns bytes consumed
|
||||||
done chan struct{}
|
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) {
|
func Pipe() (*PipeReader, *PipeWriter) {
|
||||||
pw := &PipeWriter{r: PipeReader{pipe: pipe{
|
pw := &PipeWriter{r: PipeReader{pipe: pipe{
|
||||||
wrCh: make(chan []byte), // unbuffered
|
wrCh: make(chan []byte), // unbuffered
|
||||||
@@ -868,10 +868,10 @@ func produce() <-chan int {
|
|||||||
|
|
||||||
## 10. Background Worker with Context Shutdown
|
## 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
|
```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 {
|
func OpenDB(c driver.Connector) *DB {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
db := &DB{
|
db := &DB{
|
||||||
@@ -903,10 +903,10 @@ go func() {
|
|||||||
|
|
||||||
## 11. noCopy — Preventing Value Copies
|
## 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
|
```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{}
|
type noCopy struct{}
|
||||||
|
|
||||||
// Lock is a no-op used by -copylocks checker from `go vet`.
|
// 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 |
|
| Backpressure between producer/consumer | Unbuffered channels |
|
||||||
| Long-lived background worker | Goroutine + context cancellation |
|
| Long-lived background worker | Goroutine + context cancellation |
|
||||||
| Prevent struct copying | Embed `noCopy` field |
|
| Prevent struct copying | Embed `noCopy` field |
|
||||||
|
|
||||||
|
<!-- PATTERN_COMPLETE -->
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
# Documentation Patterns in the Go Standard Library
|
# 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)
|
## 1. Package Documentation (doc.go or Package Comment)
|
||||||
|
|
||||||
**Pattern name:** Package Doc Comment
|
**Pattern name:** Package Doc Comment
|
||||||
|
|
||||||
**Source citation:** `net/http/doc.go` lines 6–30, `os/file.go` lines 5–43, `log/slog/doc.go` lines 6–30
|
**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
|
**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
|
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
|
**Pattern name:** `# Heading` in Doc Comments
|
||||||
|
|
||||||
**Source citation:** `os/file.go` lines 37–43, `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
|
**What it does:** Uses `# Section Name` within the package doc comment to organize
|
||||||
long documentation into navigable sections.
|
long documentation into navigable sections.
|
||||||
@@ -84,7 +86,7 @@ too many sections (fragmenting simple docs).
|
|||||||
|
|
||||||
**Pattern name:** `// TypeName verb...` or `// FuncName verb...`
|
**Pattern name:** `// TypeName verb...` or `// FuncName verb...`
|
||||||
|
|
||||||
**Source citation:** `net/http/server.go` lines 64–82 (Handler), `bufio/scan.go` lines 14–27 (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
|
**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.
|
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
|
**Pattern name:** `[TypeName]`, `[Package.Symbol]`, `[Method]` Links
|
||||||
|
|
||||||
**Source citation:** `net/http/server.go` lines 65–70, `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
|
**What it does:** Doc comments use `[SymbolName]` to create hyperlinks to other
|
||||||
identifiers. These render as clickable links on pkg.go.dev.
|
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()`
|
**Pattern name:** `func ExampleXxx()` / `func ExampleType_Method()`
|
||||||
|
|
||||||
**Source citation:** `regexp/example_test.go` lines 13–28, `net/http/example_handle_test.go` lines 16–31
|
**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`
|
**What it does:** Functions named `Example`, `ExampleXxx`, or `ExampleType_Method`
|
||||||
in `_test.go` files serve as both executable tests and documentation. They include
|
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
|
**Pattern name:** Indented Code Blocks in Comments
|
||||||
|
|
||||||
**Source citation:** `os/file.go` lines 17–35, `time/time.go` lines 928–933
|
**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
|
**What it does:** Doc comments include indented code snippets (4 spaces) that render
|
||||||
as preformatted code blocks in godoc.
|
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
|
**Pattern name:** `// Deprecated: ...` in Doc Comments
|
||||||
|
|
||||||
**Source citation:** `net/http/server.go` line 57 (ErrWriteAfterFlush), `os/file.go` lines 93–95
|
**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
|
**What it does:** A paragraph starting with `Deprecated:` marks an identifier as
|
||||||
deprecated and explains what to use instead.
|
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]"
|
**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
|
**What it does:** Functions document the concrete error type they return, enabling
|
||||||
callers to type-assert for additional context.
|
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
|
**Pattern name:** "Safe for concurrent use" / Concurrency Guarantees
|
||||||
|
|
||||||
**Source citation:** `net/http/transport.go` lines 79–80, `os/types.go` line 17, `regexp/regexp.go` lines 77–79
|
**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
|
**What it does:** Doc comments explicitly state the concurrency safety of a type
|
||||||
or note exceptions where concurrent use is not safe.
|
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,
|
// A Regexp is safe for concurrent use by multiple goroutines,
|
||||||
// except for configuration methods, such as [Regexp.Longest].
|
// except for configuration methods, such as [Regexp.Longest].
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- PATTERN_COMPLETE -->
|
||||||
|
|||||||
+27
-25
@@ -6,21 +6,21 @@ Patterns extracted from the Go standard library source code.
|
|||||||
|
|
||||||
## 1. Sentinel Errors
|
## 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
|
```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.
|
// EOF is the error returned by Read when no more input is available.
|
||||||
// (Read must return EOF itself, not an error wrapping EOF,
|
// (Read must return EOF itself, not an error wrapping EOF,
|
||||||
// because callers will test for EOF using ==.)
|
// because callers will test for EOF using ==.)
|
||||||
var EOF = errors.New("EOF")
|
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")
|
var ErrUnexpectedEOF = errors.New("unexpected EOF")
|
||||||
```
|
```
|
||||||
|
|
||||||
```go
|
```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")
|
var ErrUnsupported = New("unsupported operation")
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -132,15 +132,15 @@ func Read() error {
|
|||||||
|
|
||||||
## 2. errors.New — Minimal Error Construction
|
## 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
|
```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 {
|
func New(text string) error {
|
||||||
return &errorString{text}
|
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 {
|
type errorString struct {
|
||||||
s string
|
s string
|
||||||
}
|
}
|
||||||
@@ -177,10 +177,10 @@ func doThing() error {
|
|||||||
|
|
||||||
## 3. Error Wrapping with fmt.Errorf and %w
|
## 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
|
```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
|
// Errorf formats according to a format specifier and returns the string
|
||||||
// as a value that satisfies error.
|
// as a value that satisfies error.
|
||||||
//
|
//
|
||||||
@@ -190,7 +190,7 @@ func doThing() error {
|
|||||||
// Unwrap method returning a []error containing all the %w operands.
|
// Unwrap method returning a []error containing all the %w operands.
|
||||||
func Errorf(format string, a ...any) (err error) { ... }
|
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 {
|
type wrapError struct {
|
||||||
msg string
|
msg string
|
||||||
err error
|
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
|
## 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
|
```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 {
|
func Is(err, target error) bool {
|
||||||
if err == nil || target == nil {
|
if err == nil || target == nil {
|
||||||
return err == target
|
return err == target
|
||||||
@@ -377,10 +377,10 @@ if errors.Is(err, os.ErrNotExist) { ... } // works through wrapping
|
|||||||
|
|
||||||
## 5. errors.As — Extracting Error Types Through Chains
|
## 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
|
```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 {
|
func As(err error, target any) bool {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
@@ -406,7 +406,7 @@ if errors.As(err, &pathErr) {
|
|||||||
|
|
||||||
### Go 1.24+: errors.AsType (generic version)
|
### 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
|
```go
|
||||||
if perr, ok := errors.AsType[*fs.PathError](err); ok {
|
if perr, ok := errors.AsType[*fs.PathError](err); ok {
|
||||||
fmt.Println(perr.Path)
|
fmt.Println(perr.Path)
|
||||||
@@ -428,10 +428,10 @@ if errors.As(err, &pathErr) { ... } // works through wrapping
|
|||||||
|
|
||||||
## 6. errors.Join — Multi-Error Aggregation
|
## 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
|
```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 {
|
func Join(errs ...error) error {
|
||||||
n := 0
|
n := 0
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
@@ -555,7 +555,7 @@ return lastErr
|
|||||||
|
|
||||||
## 7. Custom Is() Method — Equivalence Classes
|
## 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:
|
From the `errors.Is` doc:
|
||||||
```go
|
```go
|
||||||
@@ -569,7 +569,7 @@ From the `errors.Is` doc:
|
|||||||
|
|
||||||
Real example from context:
|
Real example from context:
|
||||||
```go
|
```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{}
|
type deadlineExceededError struct{}
|
||||||
|
|
||||||
func (deadlineExceededError) Error() string { return "context deadline exceeded" }
|
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)
|
## 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
|
```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 MarshalerError struct {
|
||||||
Type reflect.Type
|
Type reflect.Type
|
||||||
Err error
|
Err error
|
||||||
@@ -650,10 +650,10 @@ func (e *MyError) Error() string { return e.Err.Error() }
|
|||||||
|
|
||||||
## 9. ErrUnsupported — Feature Detection via Errors
|
## 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
|
```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,
|
// ErrUnsupported indicates that a requested operation cannot be performed,
|
||||||
// because it is unsupported.
|
// because it is unsupported.
|
||||||
//
|
//
|
||||||
@@ -685,10 +685,10 @@ return errors.ErrUnsupported // no info about what operation or why
|
|||||||
|
|
||||||
## 10. Error String Conventions
|
## 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
|
```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 (
|
var (
|
||||||
ErrHijacked = errors.New("http: connection has been hijacked")
|
ErrHijacked = errors.New("http: connection has been hijacked")
|
||||||
ErrContentLength = errors.New("http: wrote more than the declared Content-Length")
|
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)` |
|
| Aggregate multiple errors | `errors.Join(err1, err2)` |
|
||||||
| Make custom types traversable | Implement `Unwrap() error` |
|
| Make custom types traversable | Implement `Unwrap() error` |
|
||||||
| Define error equivalence | Implement `Is(error) bool` |
|
| Define error equivalence | Implement `Is(error) bool` |
|
||||||
|
|
||||||
|
<!-- PATTERN_COMPLETE -->
|
||||||
|
|||||||
+30
-28
@@ -6,22 +6,22 @@ Patterns extracted from the Go standard library source code.
|
|||||||
|
|
||||||
## 1. Small Interfaces (1-2 Methods)
|
## 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's most powerful interfaces have exactly **one method**:
|
||||||
|
|
||||||
```go
|
```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 {
|
type Reader interface {
|
||||||
Read(p []byte) (n int, err error)
|
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 {
|
type Writer interface {
|
||||||
Write(p []byte) (n int, err error)
|
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 {
|
type Closer interface {
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
@@ -120,30 +120,30 @@ Large interfaces are hard to implement, hard to mock, and couple consumers to ca
|
|||||||
|
|
||||||
## 2. Interface Composition
|
## 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:
|
Compose small interfaces into larger ones only when needed:
|
||||||
|
|
||||||
```go
|
```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 {
|
type ReadWriter interface {
|
||||||
Reader
|
Reader
|
||||||
Writer
|
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 {
|
type ReadCloser interface {
|
||||||
Reader
|
Reader
|
||||||
Closer
|
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 {
|
type WriteCloser interface {
|
||||||
Writer
|
Writer
|
||||||
Closer
|
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 {
|
type ReadWriteCloser interface {
|
||||||
Reader
|
Reader
|
||||||
Writer
|
Writer
|
||||||
@@ -168,13 +168,13 @@ func processData(rw ReadWriteCloser) {
|
|||||||
|
|
||||||
## 3. Accept Interfaces, Return Structs
|
## 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
|
```go
|
||||||
// src/io/io.go:461
|
// src/io/io.go:461
|
||||||
func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} }
|
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 {
|
type LimitedReader struct {
|
||||||
R Reader // underlying reader
|
R Reader // underlying reader
|
||||||
N int64 // max bytes remaining
|
N int64 // max bytes remaining
|
||||||
@@ -182,7 +182,7 @@ type LimitedReader struct {
|
|||||||
```
|
```
|
||||||
|
|
||||||
```go
|
```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 {
|
func TeeReader(r Reader, w Writer) Reader {
|
||||||
return &teeReader{r, w}
|
return &teeReader{r, w}
|
||||||
}
|
}
|
||||||
@@ -272,7 +272,7 @@ func NewServer() ServerInterface // hides useful config fields
|
|||||||
|
|
||||||
## 4. Interface Satisfaction as a Compile-Time Check
|
## 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
|
```go
|
||||||
// src/io/io.go:645
|
// src/io/io.go:645
|
||||||
@@ -299,10 +299,10 @@ func doSomething(w ResponseWriter) {
|
|||||||
|
|
||||||
## 5. Interface-Based Polymorphism (sort.Interface)
|
## 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
|
```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 {
|
type Interface interface {
|
||||||
Len() int
|
Len() int
|
||||||
Less(i, j int) bool
|
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)
|
## 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
|
```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
|
// The HandlerFunc type is an adapter to allow the use of
|
||||||
// ordinary functions as HTTP handlers. If f is a function
|
// ordinary functions as HTTP handlers. If f is a function
|
||||||
// with the appropriate signature, HandlerFunc(f) is a
|
// with the appropriate signature, HandlerFunc(f) is a
|
||||||
// Handler that calls f.
|
// Handler that calls f.
|
||||||
type HandlerFunc func(ResponseWriter, *Request)
|
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).
|
// ServeHTTP calls f(w, r).
|
||||||
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
|
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
|
||||||
f(w, r)
|
f(w, r)
|
||||||
@@ -436,15 +436,15 @@ func (h myHandler) ServeHTTP(w ResponseWriter, r *Request) {
|
|||||||
|
|
||||||
## 7. Optional Interfaces (Runtime Feature Detection)
|
## 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
|
```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 {
|
type Flusher interface {
|
||||||
Flush()
|
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 {
|
type Hijacker interface {
|
||||||
Hijack() (net.Conn, *bufio.ReadWriter, error)
|
Hijack() (net.Conn, *bufio.ReadWriter, error)
|
||||||
}
|
}
|
||||||
@@ -564,10 +564,10 @@ type ResponseWriter interface {
|
|||||||
|
|
||||||
## 8. The Stringer Interface (Convention-Based Behavior)
|
## 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
|
```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 {
|
type Stringer interface {
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
@@ -596,10 +596,10 @@ func printThing(v any) string {
|
|||||||
|
|
||||||
## 9. Interface Upgrade Pattern (WriterTo/ReaderFrom in io.Copy)
|
## 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
|
```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) {
|
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.
|
// If the reader has a WriteTo method, use it to do the copy.
|
||||||
// Avoids an allocation and a copy.
|
// Avoids an allocation and a copy.
|
||||||
@@ -632,15 +632,15 @@ func Copy(dst Writer, src Reader) {
|
|||||||
|
|
||||||
## 10. The driver.Driver Pattern (Plugin Interfaces)
|
## 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
|
```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 {
|
type Driver interface {
|
||||||
Open(name string) (Conn, error)
|
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 {
|
type DriverContext interface {
|
||||||
OpenConnector(name string) (Connector, error)
|
OpenConnector(name string) (Connector, error)
|
||||||
}
|
}
|
||||||
@@ -676,3 +676,5 @@ type Driver interface {
|
|||||||
| Compile-time interface checks | `var _ Interface = (*Type)(nil)` |
|
| Compile-time interface checks | `var _ Interface = (*Type)(nil)` |
|
||||||
| Runtime interface upgrade for optimization | `io.Copy` → `WriterTo`/`ReaderFrom` |
|
| Runtime interface upgrade for optimization | `io.Copy` → `WriterTo`/`ReaderFrom` |
|
||||||
| Plugin/driver interfaces start minimal | `database/sql/driver.Driver` |
|
| Plugin/driver interfaces start minimal | `database/sql/driver.Driver` |
|
||||||
|
|
||||||
|
<!-- PATTERN_COMPLETE -->
|
||||||
|
|||||||
+13
-11
@@ -6,10 +6,10 @@ Patterns extracted from the Go standard library source code.
|
|||||||
|
|
||||||
## 1. Package-Level Documentation
|
## 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
|
```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.
|
// Package io provides basic interfaces to I/O primitives.
|
||||||
// Its primary job is to wrap existing implementations of such primitives,
|
// Its primary job is to wrap existing implementations of such primitives,
|
||||||
// such as those in package os, into shared public interfaces that
|
// such as those in package os, into shared public interfaces that
|
||||||
@@ -22,7 +22,7 @@ package io
|
|||||||
```
|
```
|
||||||
|
|
||||||
```go
|
```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
|
// Package sync provides basic synchronization primitives such as mutual
|
||||||
// exclusion locks. Other than the Once and WaitGroup types, most are intended
|
// exclusion locks. Other than the Once and WaitGroup types, most are intended
|
||||||
// for use by low-level library routines. Higher-level synchronization is
|
// for use by low-level library routines. Higher-level synchronization is
|
||||||
@@ -222,7 +222,7 @@ type Parser struct {
|
|||||||
|
|
||||||
## 5. init() Functions — Use Sparingly
|
## 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
|
```go
|
||||||
// src/net/http/http2.go:37
|
// src/net/http/http2.go:37
|
||||||
@@ -379,7 +379,7 @@ srv := &http.Server{
|
|||||||
|
|
||||||
## 7. Constructor Pattern — NewX Functions
|
## 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
|
```go
|
||||||
// src/net/http/server.go:2639
|
// src/net/http/server.go:2639
|
||||||
@@ -387,7 +387,7 @@ func NewServeMux() *ServeMux {
|
|||||||
return new(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 {
|
func OpenDB(c driver.Connector) *DB {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
db := &DB{
|
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
|
## 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
|
```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
|
// package user
|
||||||
//
|
//
|
||||||
// type key int
|
// type key int
|
||||||
@@ -508,7 +508,7 @@ The user never sees `driver.Conn`. The driver never sees `sql.DB`'s pool logic.
|
|||||||
```
|
```
|
||||||
|
|
||||||
```go
|
```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 (
|
var (
|
||||||
ServerContextKey = &contextKey{"http-server"}
|
ServerContextKey = &contextKey{"http-server"}
|
||||||
LocalAddrContextKey = &contextKey{"local-addr"}
|
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
|
## 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
|
```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) {
|
func parseTag(tag string) (string, tagOptions) {
|
||||||
tag, opt, _ := strings.Cut(tag, ",")
|
tag, opt, _ := strings.Cut(tag, ",")
|
||||||
return tag, tagOptions(opt)
|
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) |
|
| API layers | Separate user from implementor (SPI) |
|
||||||
| Context values | Unexported key type + typed accessors |
|
| Context values | Unexported key type + typed accessors |
|
||||||
| Configuration | Struct literals or functional options |
|
| Configuration | Struct literals or functional options |
|
||||||
|
|
||||||
|
<!-- PATTERN_COMPLETE -->
|
||||||
|
|||||||
+13
-9
@@ -1,10 +1,12 @@
|
|||||||
# Struct Design Patterns in the Go Standard Library
|
# 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
|
## 1. Zero-Value Usability
|
||||||
|
|
||||||
**Pattern name:** Zero Value Ready
|
**Pattern name:** Zero Value Ready
|
||||||
|
|
||||||
**Source citation:** `net/http/client.go` lines 31–35, `strings/builder.go` lines 14–16
|
**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
|
**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.
|
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
|
**Pattern name:** Indirection via Unexported Impl
|
||||||
|
|
||||||
**Source citation:** `os/types.go` lines 16–20, `os/file_unix.go` lines 59–71
|
**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
|
**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
|
(`*file`) that holds the real implementation state. Users interact only with the
|
||||||
@@ -173,7 +175,7 @@ type file struct {
|
|||||||
|
|
||||||
**Pattern name:** NewXxx Constructor
|
**Pattern name:** NewXxx Constructor
|
||||||
|
|
||||||
**Source citation:** `bufio/scan.go` lines 89–96, `bufio/bufio.go` lines 50–60
|
**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
|
**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
|
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
|
**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
|
**What it does:** Provides two constructors — one with defaults (`NewReader`) and one
|
||||||
with explicit configuration (`NewReaderSize`). The default version calls the
|
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)
|
**Pattern name:** Configuration Struct (Exported Fields, Nil-Means-Default)
|
||||||
|
|
||||||
**Source citation:** `net/http/server.go` lines 3020–3120, `crypto/tls/common.go` lines 566+, `log/slog/handler.go` lines 135–175
|
**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
|
**What it does:** A struct with exported, documented fields provides all
|
||||||
configuration knobs. Nil/zero values always mean "use the default".
|
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
|
**Pattern name:** Interface Abstraction for Pluggable Implementations
|
||||||
|
|
||||||
**Source citation:** `crypto/crypto.go` lines 180–200, `net/http/transport.go` lines 66–82
|
**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
|
**What it does:** Core behavior is defined via an interface. The package provides
|
||||||
a default concrete implementation, but any user type satisfying the interface
|
a default concrete implementation, but any user type satisfying the interface
|
||||||
@@ -485,7 +487,7 @@ type Client struct {
|
|||||||
|
|
||||||
**Pattern name:** copyCheck (Runtime Copy Detection)
|
**Pattern name:** copyCheck (Runtime Copy Detection)
|
||||||
|
|
||||||
**Source citation:** `strings/builder.go` lines 25–40
|
**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
|
**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
|
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
|
**Pattern name:** Package-Level Default Instance
|
||||||
|
|
||||||
**Source citation:** `net/http/client.go` line 109, `net/http/transport.go` lines 47–58
|
**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
|
**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.
|
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
|
**Pattern name:** Post-Construction Configuration via Methods
|
||||||
|
|
||||||
**Source citation:** `bufio/scan.go` lines 275–293
|
**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
|
**What it does:** After construction with `NewScanner`, optional configuration is
|
||||||
applied via methods (`Split`, `Buffer`) before the first call to `Scan`.
|
applied via methods (`Split`, `Buffer`) before the first call to `Scan`.
|
||||||
@@ -595,3 +597,5 @@ func (s *Scanner) Split(split SplitFunc) {
|
|||||||
s.split = split
|
s.split = split
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- PATTERN_COMPLETE -->
|
||||||
|
|||||||
+13
-9
@@ -1,5 +1,7 @@
|
|||||||
# Code Style Patterns in the Go Standard Library
|
# 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)
|
## 1. Naming Conventions: mixedCaps (No Underscores)
|
||||||
|
|
||||||
**Pattern name:** mixedCaps / MixedCaps
|
**Pattern name:** mixedCaps / MixedCaps
|
||||||
@@ -34,7 +36,7 @@ const shutdownPollIntervalMax = 500 * time.Millisecond
|
|||||||
|
|
||||||
**Pattern name:** Acronym Capitalization
|
**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)
|
**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.
|
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)`
|
**Pattern name:** `var _ Interface = (*Type)(nil)`
|
||||||
|
|
||||||
**Source citation:** `io/io.go` line 645, `os/file.go` lines 747–750, `encoding/json/stream.go` lines 280–281
|
**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
|
**What it does:** A package-level `var _ InterfaceName = (*ConcreteType)(nil)` declares
|
||||||
that the concrete type must satisfy the interface. The compiler verifies this at
|
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)
|
**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
|
**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.
|
(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()`
|
**Pattern name:** `defer mu.Unlock()` / `defer f.Close()`
|
||||||
|
|
||||||
**Source citation:** `net/http/server.go` lines 3173–3174, `net/http/example_handle_test.go` lines 21–22
|
**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
|
**What it does:** Resources acquired at the top of a scope are immediately deferred
|
||||||
for cleanup. Mutexes are locked then immediately `defer Unlock()`'d.
|
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
|
**Pattern name:** Sentinel Errors + Structured Error Types
|
||||||
|
|
||||||
**Source citation:** `os/error.go` lines 14–27, `os/error.go` lines 46–67
|
**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
|
**What it does:** Package-level sentinel errors (`ErrNotExist`, `ErrPermission`) are
|
||||||
declared as `var` for use with `errors.Is()`. Structured error types (`*PathError`,
|
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
|
**Pattern name:** Typed Constants with iota
|
||||||
|
|
||||||
**Source citation:** `crypto/crypto.go` lines 70–85, `time/time.go` lines 936–943
|
**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
|
**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
|
a named type and `iota` for sequential values. Constants of the same type
|
||||||
@@ -463,7 +465,7 @@ const (
|
|||||||
|
|
||||||
**Pattern name:** `// guards x` Field Comments
|
**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
|
**What it does:** When a sync primitive (mutex) protects specific fields, a brief
|
||||||
comment documents what it guards: `mu sync.Mutex // guards n`.
|
comment documents what it guards: `mu sync.Mutex // guards n`.
|
||||||
@@ -490,7 +492,7 @@ type countHandler struct {
|
|||||||
|
|
||||||
**Pattern name:** Named Type for Semantic Units
|
**Pattern name:** Named Type for Semantic Units
|
||||||
|
|
||||||
**Source citation:** `time/time.go` lines 915–943
|
**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.
|
**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
|
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)
|
**Pattern name:** Grouped Imports (stdlib / external / internal)
|
||||||
|
|
||||||
**Source citation:** `net/http/server.go` lines 8–36
|
**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:
|
**What it does:** Imports are organized in groups separated by blank lines:
|
||||||
1. Standard library
|
1. Standard library
|
||||||
@@ -641,3 +643,5 @@ import (
|
|||||||
"golang.org/x/net/http/httpguts"
|
"golang.org/x/net/http/httpguts"
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- PATTERN_COMPLETE -->
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# Advanced Go Testing Patterns
|
# 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.
|
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
|
### 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.
|
**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)
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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.
|
**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
|
### 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).
|
**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:
|
// Usage:
|
||||||
cst.ts.Config.ErrorLog = log.New(testLogWriter{t}, "", 0)
|
cst.ts.Config.ErrorLog = log.New(testLogWriter{t}, "", 0)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- PATTERN_COMPLETE -->
|
||||||
|
|||||||
Reference in New Issue
Block a user