<< All versions
Skill v1.0.0
currentAutomated scan100/100lugassawan/swe-workbench/language-go
──Details
PublishedSeptember 27, 2026 at 11:39 PM
Content Hashsha256:e5bf9acb5595cdf9...
Git SHA
──Files
Files (1 file, 4.7 KB)
SKILL.md4.7 KBactive
SKILL.md · 114 lines · 4.7 KB
version: "1.0.0" name: language-go description: Go idioms — error handling, concurrency, and standard library usage. Auto-load when working with .go files, go.mod, go.sum, or when the user mentions Go, Golang, goroutines, channels, context, or error wrapping.
Go
Errors are values
- Return
error; do notpanicacross package boundaries. - Wrap with
fmt.Errorf("doing X: %w", err)to preserve the chain. - Inspect with
errors.Isanderrors.As. Never string-match messages. - Sentinel errors (
var ErrNotFound = errors.New(...)) for expected cases; typed errors when callers need structured data.
go
if err != nil {return fmt.Errorf("load user %s: %w", id, err)}
Interfaces — small, defined by the consumer
- Define interfaces in the package that uses them, not where concrete types live.
- Single-method interfaces are normal (
io.Reader,io.Closer). - Accept interfaces, return concrete types.
Concurrency
- A goroutine without a known termination path is a leak. Always know who stops it.
context.Contextplumbs cancellation and deadlines — first parameter, namedctx.- Channels for ownership transfer; mutexes for protecting state. A
sync.Mutexis often simpler than a goroutine. errgroup.Groupfor structured concurrency with error propagation.
go
g, ctx := errgroup.WithContext(ctx)for _, job := range jobs {job := jobg.Go(func() error { return process(ctx, job) })}if err := g.Wait(); err != nil { return err }
Context rules
ctxis the first parameter of any blocking or IO function.- Never store
context.Contextin a struct field. - Don't use
context.Valuefor required parameters — only cross-cutting concerns like request IDs.
Code generation
- A
// Code generated ... DO NOT EDIT.header means the file is output, not source. Never hand-edit it — edits are clobbered on the next run and drift from their input. - Edit the generator's input, then regenerate with
go generate ./...(or the tool directly). Commit the regenerated file with the source change. - Applies to
stringer,mockgen,sqlc,protoc-gen-go, and google/wire.
google/wire — detected by a wire.go tagged //go:build wireinject plus a wire_gen.go carrying the Wire DO NOT EDIT. header. To change dependency injection:
- Edit provider sets / injectors in
wire.goonly — neverwire_gen.go. - Regenerate with
go generate ./...(orwire ./...), then stage the updatedwire_gen.go. Ifgo generate ./...produces no diff,wire.golikely lacks a//go:generate wiredirective — runwire ./...directly.
go
//go:build wireinject// wire.go — edit here: provider sets and injector signatures.func InitApp(ctx context.Context) (*App, error) {wire.Build(configSet, storeSet, NewApp)return nil, nil // wire fills the body in wire_gen.go}
Doc comments
- godoc — the comment starts with the symbol name and reads as one full sentence;
go docrenders it verbatim. - One sentence covers most exported symbols; expand only for a non-obvious contract (surprising panics, blocking behavior, ownership transfer).
go
// Fetch returns the user with the given id, or ErrNotFound if none exists.func Fetch(ctx context.Context, id string) (*User, error) { ... }
Tooling
- Imports:
goimports -w . - Format:
gofmt -w .(redundant if running goimports; keep for explicit CI parity) - Lint:
go vet ./...+golangci-lint run - Test:
go test ./...(see Testing below)
Testing
- Table-driven tests are the default.
t.Run(name, ...)for subtests.t.Cleanupbeatsdeferfor shared fixtures.httptest.Serverfor HTTP;testing/iotestfor edge IO.
go
for _, c := range cases {t.Run(c.name, func(t *testing.T) {if got := Add(c.a, c.b); got != c.want {t.Errorf("Add(%d,%d) = %d, want %d", c.a, c.b, got, c.want)}})}
Package design
- Package name = its purpose, lower-case, no underscores.
- Avoid
util,common,helpers. Name by the domain thing it owns. - Cyclic imports are a design smell — break with an interface in the consuming package.
Idioms cheat sheet
if err := do(); err != nil { ... }— keep errors close to their cause.- Zero values are useful — design types so zero works.
deferfor cleanup;deferin a loop accumulates.- Exported fields beat getters/setters unless behavior needs them.
anyoverinterface{}in new code.- Prefer
slices,maps,cmpfrom stdlib over hand-rolled helpers.
Avoid
- Naked returns outside tiny functions.
panicas flow control.- Empty interfaces in public APIs without a strong reason.
- Over-generics — use them only when they clearly reduce duplication.