Go
SkillSecurityIdiomatic Go 1.25 practices: errors, interfaces, concurrency, generics, testing, security, tooling. Use when writing or reviewing Go code.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Go skill
What this skill tells your AI
The instructions your AI receives, as published by sumonmselim/agentguard in skills/go/SKILL.md and read by ahel’s review.
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
Signals
- GitHub stars
- 56
- Forks
- 11
- Last commit
- Jul 2026
Advanced
- Catalog kind
- skill
- Gateway key
go-sumonmselim- Source
- github.com/sumonmselim/agentguard