From go-agent-skills
Modernizes Go code to use current language features (generics, log/slog, errors.Join, slices/maps, range-over-func, iterators) for Go 1.21+.
How this skill is triggered — by the user, by Claude, or both
Slash command
/go-agent-skills:go-modernizeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Go evolves. Code written for Go 1.16 should not look the same as code targeting
Go evolves. Code written for Go 1.16 should not look the same as code targeting
Go 1.22+. Modernize incrementally — update go.mod, then adopt new patterns.
Detailed reference material, loaded on demand:
references/generics.md — replacing interface{} with type parameters,
constraints, generic containers, when NOT to use generics.references/stdlib-migrations.md — before/after examples for slog,
errors.Join, slices/maps helpers, range-over-int, and iterators.Read a reference file only when the summary below is not enough.
Check the go directive in go.mod — it caps which features you can use.
Run the official modernize analyzer first — it finds and fixes the mechanical migrations automatically:
go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix -test ./...
If the command is unavailable in your environment, apply the table below manually instead.
Scan the table below for the judgment-based migrations the analyzer does not cover (generics, iterators, logger replacement) and apply them case by case.
Run go build ./... and the test suite after each group of changes.
| Go Version | Feature | Action |
|---|---|---|
| 1.13+ | errors.Is, errors.As | Replace == error comparisons |
| 1.13+ | http.NewRequestWithContext | Replace http.NewRequest |
| 1.16+ | embed | Replace go-bindata / packr |
| 1.18+ | Generics | Replace interface{} utility functions |
| 1.20+ | errors.Join | Replace manual error accumulation |
| 1.21+ | log/slog | Replace log for structured logging |
| 1.21+ | slices, maps | Replace hand-written slice/map utilities |
| 1.21+ | min, max builtins | Replace math.Min/math.Max (float64-only) |
| 1.22+ | Range over int | Replace for i := 0; i < n; i++ |
| 1.23+ | Range over func | Replace callback-based iteration |
// ❌ Before — loses type safety
func Contains(slice []interface{}, target interface{}) bool { /* ... */ }
// ✅ After — type-safe generic
func Contains[T comparable](slice []T, target T) bool { /* ... */ }
Use generics for container types (Set[T], Result[T]) and utility
functions. Do NOT use them where a single concrete type works, or as a
substitute for interfaces in runtime polymorphism.
Details and constraint patterns: references/generics.md.
// ❌ Before
log.Printf("processing order %s for user %s", orderID, userID)
// ✅ After
slog.Info("processing order",
slog.String("order_id", orderID),
slog.String("user_id", userID),
)
Keep zap/zerolog only if you need their performance for high-throughput logging; for most services slog is sufficient.
var errs []error
for _, item := range items {
if err := validate(item); err != nil {
errs = append(errs, err)
}
}
if err := errors.Join(errs...); err != nil {
return fmt.Errorf("validation: %w", err)
}
errors.Join preserves the chain — errors.Is/errors.As work on each
joined error. Never accumulate error strings manually.
found := slices.Contains(items, target) // not a manual loop
slices.SortFunc(users, func(a, b User) int { // not sort.Slice
return cmp.Compare(a.Name, b.Name)
})
keys := slices.Collect(maps.Keys(m)) // not a manual key loop
clone := maps.Clone(m) // not a manual copy loop
for i := range n { process(i) } // not for i := 0; i < n; i++
for i, v := range slices.Backward(items) { // stdlib iterators
fmt.Printf("%d: %v\n", i, v)
}
Custom iter.Seq/iter.Seq2 iterators replace callback-based iteration —
full worked example in references/stdlib-migrations.md.
// ❌ Before — request without context
req, err := http.NewRequest(http.MethodGet, url, nil)
// ✅ After — context propagated
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
go.mod version matches the features used in the codebaseinterface{} where any or type parameters would be clearerlog/slog used instead of log.Printf for structured loggingerrors.Join used instead of manual error string concatenationslices.Contains, slices.SortFunc, maps.Clone replace hand-written loopsfor i := range n) used where applicablehttp.NewRequestWithContext used instead of http.NewRequestsort.Slice — use slices.SortFunc with cmp.Comparenpx claudepluginhub eduardo-sl/go-agent-skills --plugin go-agent-skillsModernizes Go code to use recent language features, standard library improvements, and idiomatic patterns. Scans for deprecated APIs, language upgrades, and tooling improvements.
Applies modern Go syntax guidelines and features (slices, maps, cmp, min/max, etc.) based on project's detected Go version from go.mod. Avoids outdated patterns.
Applies Go best practices for performance, modern syntax, generics, patterns, testing, error handling, and concurrency when writing or reviewing Go code.