Idiomatic Go 1.25 practices: errors, interfaces, concurrency, generics, testing, security, tooling. Use when writing or reviewing Go code.
Install
mkdir -p .claude/skills/go-sumonmselim && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15412" && unzip -o skill.zip -d .claude/skills/go-sumonmselim && rm skill.zipInstalls to .claude/skills/go-sumonmselim
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Idiomatic Go 1.25 practices: errors, interfaces, concurrency, generics, testing, security, tooling. Use when writing or reviewing Go code.138 chars✓ has a “when” trigger
About this skill
Go
Project structure
go.modat repo root. Module path matches repo URL:module github.com/org/repo- Pin Go version in
go.mod:go 1.25. Toolchain auto-selects viatoolchaindirective - Tool dependencies via
go.modtooldirectives (1.24+).go get -tool golang.org/x/tools/cmd/stringer - Standard layout:
cmd/for binaries,internal/for private packages,pkg/only if genuinely public - No circular imports.
internal/enforces package boundaries go.sumcommitted. Never manually edited
Errors
- Errors are values. Return
erroras last return value - Wrap with context:
fmt.Errorf("op failed: %w", err). Always%w, not%v, when caller may inspect - Sentinel errors:
var ErrNotFound = errors.New("not found"). Useerrors.Isto check, not== - Custom error types: implement
Error() string. Useerrors.Asto extract - Never ignore errors.
_ = f()only with explicit justification in comment - No
panicin library code. Reserve for truly unrecoverable states inmain - Check errors immediately after call. No deferred error checks buried in logic
Interfaces
- Define interfaces at point of use (consumer), not point of implementation
- Small interfaces. Prefer single-method interfaces:
io.Reader,io.Writer - Accept interfaces, return concrete types
- No interface for a single implementation unless testing or future extensibility is clear
interface{}→any(Go 1.18+). Useanyeverywhere- Embed interfaces to compose:
type ReadWriter interface { Reader; Writer }
Generics
- Use generics to eliminate identical logic across types. Not for premature abstraction
- Constrain tightly:
[T int | int64]over[T any]when type matters comparableconstraint for map keys and equality checksgolang.org/x/exp/slicesandmapspatterns now in stdlib (slices,mapspackages, 1.21+)- Range over func iterators (1.22+): use
iter.Seqanditer.Seq2for custom iterables - Generic type aliases fully supported (1.24+):
type Set[T comparable] = map[T]struct{}
Concurrency
- Share memory by communicating. Channels for ownership transfer,
syncfor shared state - Always specify goroutine lifecycle: who starts it, who stops it, how caller knows it's done
context.Contextas first arg to every blocking or long-running function. Respect cancellationselectwithctx.Done()in every goroutine that blocks on channel or I/Osync.WaitGroupto wait for goroutine group.errgroup.Groupwhen any error should cancel allsync.Mutexover channels for protecting shared state. Embed mutex with the data it protects- Race detector always on in tests and CI:
go test -race ./... - No goroutine leaks. Profile with
goleakin tests for long-running services - Buffered channels: document capacity rationale. Default to unbuffered
- GOMAXPROCS defaults to cgroup CPU limit on Linux (1.25+) — container deployments no longer need manual tuning
Context
context.Background()at program entry only (main, top-level server handler, test root)- Never store context in struct. Pass explicitly
- Cancel functions always deferred:
ctx, cancel := context.WithTimeout(...); defer cancel() - Propagate deadlines from inbound requests to all outbound calls (HTTP, DB, gRPC)
context.WithValueonly for request-scoped metadata (trace ID, auth token). Not for optional function params. Key type must be unexported to avoid collisions
HTTP and networking
net/http: always setReadTimeout,WriteTimeout,IdleTimeoutonhttp.Server. No default server- Close response bodies:
defer resp.Body.Close()immediately after nil error check - Use
http.NewRequestWithContext— neverhttp.NewRequestin production code - Validate and sanitize all inbound data. Use
net/urlfor URL construction, not string concat - TLS:
tls.ConfigwithMinVersion: tls.VersionTLS12. Prefer TLS 1.3
Security
- Never construct SQL with string concat. Use parameterized queries or an ORM that does
crypto/randfor all random tokens, IDs, secrets. Nevermath/rand- Hash passwords with
bcryptorargon2. Neversha256ormd5for passwords - Avoid
html/templatebypass (template.HTML,template.JS). Auto-escaping is the point os/exec: never pass user input directly to shell. Use arg list form, not string formfilepath.Cleanandfilepath.Joinfor all path construction. Validate result stays within allowed rootgovulncheck ./...in CI. Scans modules and call graph for known CVEs- Secrets from env or secret manager at startup. Never hardcoded or in config files committed to git
Testing
- Table-driven tests as default pattern.
t.Runper case t.Parallel()in all unit tests that don't share mutable statetestify/assertor stdlibcmpfor assertions. Avoid rolling custom diff logic- Use
t.TempDir()for temp files — auto-cleaned. Neveros.TempDir()directly in tests - Fuzz tests (
func FuzzX(f *testing.F)) for parsers, decoders, untrusted input handlers - Benchmarks (
func BenchmarkX(b *testing.B)) for hot paths. Run with-benchmem httptest.NewRecorderandhttptest.NewServerfor HTTP handler tests. No real network in unit tests- Coverage:
go test -cover ./.... Track but don't cargo-cult 100% - Integration and unit tests separated via build tags:
//go:build integration
Tooling
- Format:
gofmtorgoimportson save. No style debates - Lint:
golangci-lintwith at minimumerrcheck,govet,staticcheck,gosecenabled go vet ./...in CI. Catches real bugs, not stylegovulncheck ./...in CI for supply chain securitygo mod tidybefore every commit. Keepsgo.sumcleango build -trimpathfor reproducible builds. Removes local paths from binaries- Multi-platform:
GOOS=linux GOARCH=amd64 go build. Test on target arch in CI go tool pproffor CPU/memory profiling.net/http/pprofendpoint in long-running services (behind auth)
Performance
- Preallocate slices and maps when length known:
make([]T, 0, n),make(map[K]V, n) - Avoid allocations in hot paths. Benchmark before optimizing.
go test -benchmem sync.Poolfor frequently allocated short-lived objects (e.g. buffers)- String builder:
strings.Builderfor loops. Never+=string concat in loops io.Reader/io.Writerchains over loading full content into memory- Profile first.
pprofbefore any micro-optimization