go-core-idioms
SkillMonitoring & opsUse when writing or reviewing idiomatic sequential Go — error handling, slog logging, generics, interfaces, style. Not for concurrency (go-concurrency).
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-core-idioms skill
What this skill tells your AI
The instructions your AI receives, as published by fusengine/agents in plugins/go-expert/skills/go-core-idioms/SKILL.md and read by ahel’s review.
Go Core Idioms
Idiomatic sequential Go for 1.26. For anything touching goroutines, channels,
errgroup, or context cancellation, use go-concurrency instead.
Agent Workflow (MANDATORY)
Before ANY implementation, spawn 3 agents in parallel, one Agent call each with a name:
- fuse-ai-pilot:explore-codebase - Map existing error/logging/interface patterns
- fuse-ai-pilot:research-expert - Verify latest Go docs via Context7/Exa
- mcp__context7__query-docs - Confirm stdlib signatures (errors, log/slog)
After implementation, run fuse-ai-pilot:sniper for validation.
Overview
| Feature | Description |
|---|---|
| Error handling | Explicit if err != nil, %w wrapping, errors.Join, errors.AsType (1.26) |
| Structured logging | log/slog stdlib — handlers, attrs, groups, LogValuer |
| Generics | Type params, constraints, self-referential types (1.26) |
| Interfaces | Small, consumer-side — "accept interfaces, return structs" |
| Modernizers | go fix auto-applies dozens of idiom/API fixers (1.26) |
Critical Rules
- Explicit
if err != nil- No sugar exists; never discard with_ = err - Wrap with
%w, not%v- Preserves the chain forerrors.Is/As/AsType - Accept interfaces, return structs - Define interfaces where consumed, not where produced
- Value receivers by default - Use pointer receivers only for mutation or large structs
- Run
go fix+go vet- Let modernizers migrate to current idioms (1.26)
Architecture
internal/
├── user/
│ ├── user.go # struct + value-receiver methods
│ ├── errors.go # sentinel + typed errors
│ └── repository.go # consumer-side interface, concrete struct returned
└── platform/
└── logging/
└── logger.go # slog setup, one *slog.Logger injected downward
→ See error-patterns.md for full example
Reference Guide
Concepts
| Topic | Reference | When to Consult |
|---|---|---|
| Error handling | error-handling.md | Wrapping, sentinels, errors.Join, AsType |
| Structured logging | slog-logging.md | Choosing handlers, attrs, groups, perf |
| Generics & 1.26 | generics-and-1.26.md | Type params, self-ref types, new(expr) |
| Interfaces & style | interfaces-and-style.md | Interface placement, naming, receivers |
Templates
| Template | When to Use |
|---|---|
| error-patterns.md | Building an error strategy for a package |
| slog-setup.md | Wiring a structured logger into an app |
Quick Reference
Wrap and inspect errors
if err != nil {
return fmt.Errorf("load user %d: %w", id, err) // %w keeps the chain
}
// 1.26: type-safe, generic replacement for errors.As
if pathErr, ok := errors.AsType[*fs.PathError](err); ok {
log.Printf("failed path: %s", pathErr.Path)
}
→ See error-handling.md
Structured logging with slog
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("user created", "id", id, slog.Duration("took", elapsed))
→ See slog-logging.md
Best Practices
DO
- Keep interfaces one-to-three methods, named at the call site
- Add context on the way up with
%w; check witherrors.Is/AsType - Use
slog.LogAttrson hot paths to avoid allocation - Run
go fixto adopt current APIs and idioms automatically (1.26)
DON'T
- Swallow errors (
_ = err) or return bareerrwhen context helps - Define interfaces next to their implementation "just in case"
- Reach for pointer receivers without a mutation or size reason
- Write Java-esque getters/setters or
IFoointerface prefixes
Signals
- GitHub stars
- 27
- Forks
- 4
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
go-core-idioms- Source
- github.com/fusengine/agents