Writing Go
Idiomatic Go 1.25+ development.
by julianobarbosa · MIT
The skill
Idiomatic Go 1.25+ development. Use when writing Go code, designing APIs, discussing Go patterns, or reviewing Go implementations. Emphasizes stdlib, concrete types, simple error handling, and minimal dependencies.
Go Development (1.25+)
Core Principles
- Stdlib first: External deps only when justified
- Concrete types: Define interfaces at consumer, return structs
- Composition: Over inheritance, always
- Fail fast: Clear errors with context
- Simple: The obvious solution is usually correct
Quick Patterns
Error Handling
if err := doThing(); err != nil {
return fmt.Errorf("do thing: %w", err)
}
Struct with Options
type Server struct {
addr string
timeout time.Duration
}
func NewServer(addr string, opts ...Option) *Server {
s := &Server{addr: addr, timeout: 30 * time.Second}
for _, opt := range opts {
opt(s)
}
return s
}
Table-Driven Tests
tests := []struct {
name string
input string
want string
wantErr bool
}{
{"valid", "hello", "HELLO", false},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Process(tt.input)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
Go 1.25 Features
- testing/synctest: Deterministic concurrent testing with simulated clock
- encoding/json/v2: Experimental, 3-10x faster (GOEXPERIMENT=jsonv2)
- runtime/trace.FlightRecorder: Production trace capture on-demand
- Container-aware GOMAXPROCS: Auto-detects cgroup limits
- GreenTea GC: Experimental, lower latency (GOEXPERIMENT=greenteagc)
References
- PATTERNS.md - Detailed code patterns
- TESTING.md - Testing strategies with testify/mockery
- CLI.md - CLI application patterns
Tooling
go build ./... # Build
go test -race ./... # Test with race detector
golangci-lint run # Lint
mockery --all # Generate mocks
Gotchas
nilchannel sends/receives block forever; closed channel receives return zero value immediately —selectwith a nil channel case disables that case, useful pattern but easy to do accidentally.defercaptures arguments at the call site, not at execution —defer fmt.Println(time.Now())captures NOW, not the deferred time.- Pre-Go 1.22 for-loop variable capture closures over ONE variable across all iterations — the goroutine-in-loop bug. Go 1.22 changed semantics; old habits create subtle bugs in mixed-version code.
errors.IswalksUnwrap()chains, BUT if a wrapped error implementsIs(target error) boolitself, that custom Is wins over walking — confusing when migrating from xerrors.sync.Poolitems can be GC'd betweenGetand the nextPut— never rely on a Pool to retain state.
Use this skill
Connect your agent to the Skill Store MCP server and ask for it by ref: julianobarbosa/writing-go-26229694816.
Details
- Publisher
- julianobarbosa
- Category
- Software Development › Languages & frameworks
- License
- MIT
- Updated
- 2026-10-14
References
More from julianobarbosa
- 1Password Guide for implementing 1Password secrets management - CLI operations, service accounts, Developer…
- Ad Onprem Ldap Manage on-premises Active Directory users and groups from macOS or Linux over LDAPS with a bun CL…
- Alz Accelerator Deploy Azure Landing Zones using the ALZ Accelerator with AVM (Azure Verified Modules).
- Argocdclusterbootstrapping Complete ArgoCD cluster bootstrapping skill for diagnosing sync failures, creating root Applicati…