plugins/go-dev/skills/writing-go/SKILL.md
Idiomatic Go 1.25+ development. Use when writing Go code, designing APIs, discussing Go patterns, or reviewing Go implementations. Emphasizes stdlib, concrete types, simple error handling, and minimal dependencies.
npx skillsauth add alexei-led/claude-code-config writing-goInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
net/http, encoding/json, context, and testing where practical before adding dependencies.error, not panic; wrap with context using %w; avoid custom error hierarchies unless callers need distinct behavior.t.Run; stdlib testing is enough unless the project already uses another test library.context.Context through API boundaries and map service errors to HTTP status at the edge.Stdlib and Mature Libraries First
Concrete Types Over any
interface{} or any when concrete type worksPrivate Interfaces at Consumer
Flat Control Flow
Explicit Error Handling
errors.Is()/errors.As()return err// service/user.go - private interface where it's USED
type userStore interface {
Get(ctx context.Context, id string) (*User, error)
}
type Service struct {
store userStore // accepts interface
}
// repo/postgres.go - returns concrete type
func NewPostgresStore(db *sql.DB) *PostgresStore {
return &PostgresStore{db: db}
}
// GOOD: guard clauses, early returns
func process(user *User) error {
if user == nil {
return ErrNilUser
}
if user.Email == "" {
return ErrMissingEmail
}
if !isValidEmail(user.Email) {
return ErrInvalidEmail
}
return doWork(user)
}
// BAD: nested conditions
func process(user *User) error {
if user != nil {
if user.Email != "" {
if isValidEmail(user.Email) {
return doWork(user)
}
}
}
return nil
}
if err := doThing(); err != nil {
return fmt.Errorf("do thing: %w", err) // always wrap
}
// Sentinel errors
if errors.Is(err, ErrNotFound) {
return http.StatusNotFound
}
any)// GOOD: concrete types
func ProcessUsers(users []User) error { ... }
func GetUserByID(id string) (*User, error) { ... }
// BAD: unnecessary any
func ProcessItems(items []any) error { ... }
func GetByID(id any) (any, error) { ... }
tests := []struct {
name string
input string
want string
wantErr bool
}{
{"valid", "hello", "HELLO", false},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Process(tt.input)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
go build ./... # Build
go test -race ./... # Test with race detector
golangci-lint run # Lint
mockery --all # Generate mocks
After generating code, always verify it compiles, tests pass, and lint runs when configured:
go test ./...
go test -race ./...
go vet ./...
golangci-lint run ./...
Use the project's configured commands if different.
tools
Idiomatic shell development for POSIX sh, Bash, Zsh, Fish, hooks, CI shell steps, and scriptable CLI glue. Use when writing or changing `.sh`, `.bash`, `.zsh`, `.fish`, `.bats`, shell functions, shell pipelines, or command-runner recipes. Emphasizes portability, quoting, safe filesystem/process handling, non-TUI CLI tools, ShellCheck, shfmt, Bats, and ShellSpec. NOT for Python, TypeScript, Go, web code, or infrastructure operations.
tools
Use when planning, executing, checkpointing, finishing, or inspecting lightweight spec-driven work. Runs one task at a time using `.spec/` markdown files and the bundled `specctl` helper. NOT for broad product discovery beyond a short requirement interview.
testing
Author, inspect, troubleshoot, and review infrastructure across IaC, Kubernetes, cloud resources, containers, CI/CD, and Linux hosts. Use when changing Terraform/OpenTofu, Kubernetes, Helm, Kustomize, Dockerfiles, GitHub Actions, AWS, GCP, Cloud Run, BigQuery, IAM, logs, instances, or service health. NOT for deploy/apply/rollback workflows (see deploying-infra). NOT for shell scripts or generic command pipelines (see writing-shell).
development
Configure safe git workflow hygiene: pre-commit/pre-push hooks, Gitleaks secret scanning, .gitignore rules, local git config, and guardrails. Use when setting up git hooks, gitleaks/git leaks, staged pre-commit checks, pre-push validation, core.hooksPath, .gitignore, or git config best practices. NOT for creating commits (use committing-code), cleaning branches/worktrees (use cleanup-git), or creating worktrees (use using-git-worktrees).