
golang-idioms
Idiomatic Go patterns for error handling, interfaces, concurrency, testing, and module management
- Installs
- 189
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/rohitg00/awesome-claude-code-toolkit --skill golang-idioms- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads golang-idioms automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Go Idioms
Error Handling
// Return errors, never panic in library code
func LoadConfig(path string) (Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return Config{}, fmt.Errorf("reading config %s: %w", path, err)
}
var cfg Config
if err := json.Unmarshal(data, &cfg); err != nil {
return Config{}, fmt.Errorf("parsing config: %w", err)
}
return cfg, nil
}
Rules:
- Always wrap errors with context using
fmt.Errorf("context: %w", err) - Use
%wto allow callers to useerrors.Isanderrors.As - Handle errors at the appropriate level; do not log and return the same error
- Define sentinel errors for expected conditions
var (
ErrNotFound = errors.New("not found")
ErrUnauthorized = errors.New("unauthorized")
)
func GetUser(id string) (User, error) {
user, ok := store[id]
if !ok {
return User{}, fmt.Errorf("user %s: %w", id, ErrNotFound)
}
return user, nil
}
// Caller
user, err := GetUser(id)
if errors.Is(err, ErrNotFound) {
http.Error(w, "user not found", http.StatusNotFound)
return
}
Interface Design
// Keep interfaces small (1-3 methods)
type Reader interface {
Read(p []byte) (n int, err error)
}
type UserStore interface {
GetUser(ctx context.Context, id string) (User, error)
CreateUser(ctx context.Context, u User) error
}
// Accept interfaces, return structs
func NewService(store UserStore, logger *slog.Logger) *Service {
return &Service{store: store, logger: logger}
}
Rules:
- Define interfaces where they are used (consumer side), not where they are implemented
- Prefer small, composable interfaces over large ones
- Use
io.Reader,io.Writer,fmt.Stringerfrom the standard library - An interface with one method should be named after the method +
ersuffix
Goroutine and Channel Patterns
Worker Pool
func process(ctx context.Context, jobs <-chan Job, workers int) <-chan Result {
results := make(chan Result, workers)
var wg sync.WaitGroup
for range workers {
wg.Add(1)
go func() {
defer wg.Done()
for job := range jobs {
select {
case <-ctx.Done():
return
case results <- job.Execute():
}
}
}()
}
go func() {
wg.Wait()
close(results)
}()
return results
}
Fan-out/Fan-in
func fanOut[T, R any](ctx context.Context, items []T, fn func(T) R, concurrency int) []R {
sem := make(chan struct{}, concurrency)
results := make([]R, len(items))
var wg sync.WaitGroup
for i, item := range items {
wg.Add(1)
sem <- struct{}{}
go func() {
defer func() { <-sem; wg.Done() }()
results[i] = fn(item)
}()
}
wg.Wait()
return results
}
Rules:
- Always pass
context.Contextas the first parameter - Always ensure goroutines can be stopped (via context cancellation or channel close)
- Use
sync.WaitGroupto wait for goroutine completion - Use buffered channels when producer and consumer run at different speeds
- Never start a goroutine without knowing how it will stop
Context Propagation
func (s *Service) HandleRequest(ctx context.Context, req Request) (Response, error) {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
user, err := s.store.GetUser(ctx, req.UserID)
if err != nil {
return Response{}, fmt.Errorf("getting user: %w", err)
}
ctx = context.WithValue(ctx, userKey, user)
return s.processRequest(ctx, req)
}
Rules:
- Pass context as the first parameter of every function that does I/O
- Use
context.WithTimeoutorcontext.WithDeadlinefor all external calls - Always
defer cancel()after creating a cancellable context - Use
context.WithValuesparingly (request-scoped values only: trace IDs, auth info) - Never store context in a struct
Table-Driven Tests
func TestValidateEmail(t *testing.T) {
tests := []struct {
name string
email string
want bool
}{
{"valid email", "user@example.com", true},
{"missing @", "userexample.com", false},
{"empty string", "", false},
{"multiple @", "user@@example.com", false},
{"valid with subdomain", "user@mail.example.com", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ValidateEmail(tt.email)
if got != tt.want {
t.Errorf("ValidateEmail(%q) = %v, want %v", tt.email, got, tt.want)
}
})
}
}
Test Helpers
func newTestServer(t *testing.T) *httptest.Server {
t.Helper()
handler := setupRoutes()
srv := httptest.NewServer(handler)
t.Cleanup(srv.Close)
return srv
}
func assertEqual[T comparable](t *testing.T, got, want T) {
t.Helper()
if got != want {
t.Errorf("got %v, want %v", got, want)
}
}
Use t.Helper() in all test utility functions. Use t.Cleanup() instead of defer for test resource cleanup. Use testdata/ directory for test fixtures.
Module Management
go.mod structure:
module github.com/org/project
go 1.23
require (
github.com/lib/pq v1.10.9
golang.org/x/sync v0.7.0
)
Commands:
go mod tidy # remove unused, add missing
go mod verify # verify checksums
go list -m -u all # check for updates
go get -u ./... # update all dependencies
go mod vendor # vendor dependencies (optional)
Use go mod tidy before every commit. Pin major versions. Review changelogs before updating.
Zero-Value Design
Design types so their zero value is useful:
// sync.Mutex zero value is an unlocked mutex (ready to use)
var mu sync.Mutex
// bytes.Buffer zero value is an empty buffer (ready to use)
var buf bytes.Buffer
buf.WriteString("hello")
// Custom types: make zero value meaningful
type Server struct {
Addr string // defaults to ""
Handler http.Handler // defaults to nil
Timeout time.Duration // defaults to 0 (no timeout)
}
func (s *Server) ListenAndServe() error {
addr := s.Addr
if addr == "" {
addr = ":8080" // useful default
}
handler := s.Handler
if handler == nil {
handler = http.DefaultServeMux
}
// ...
}
Rules:
- Prefer structs with meaningful zero values over constructors
- Use pointer receivers when the method modifies the receiver
- Use value receivers when the method only reads
- Never export fields that users should not set directly; use constructor functions
Structured Logging
import "log/slog"
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
}))
logger.Info("request handled",
slog.String("method", r.Method),
slog.String("path", r.URL.Path),
slog.Int("status", status),
slog.Duration("latency", time.Since(start)),
)
Use log/slog (standard library, Go 1.21+). Use structured fields, never string interpolation. Include request ID, user ID, and operation name in every log entry.
Common Anti-Patterns
- Returning
interface{}/anyinstead of concrete types - Using
init()for complex setup (makes testing hard) - Ignoring errors with
_without comment - Using goroutines without lifecycle management
- Mutex contention from overly broad lock scope
- Channel misuse: prefer mutexes for simple shared state
- Naked returns in functions longer than a few lines
FAQ
What does the golang-idioms skill do?
Idiomatic Go patterns for error handling, interfaces, concurrency, testing, and module management
How do I install golang-idioms?
Run npx skills add https://github.com/rohitg00/awesome-claude-code-toolkit --skill golang-idioms in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/golang-idioms/ (personal) or .claude/skills/golang-idioms/ (project).
Which AI agents can use golang-idioms?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is golang-idioms safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains golang-idioms?
It is published by rohitg00 in rohitg00/awesome-claude-code-toolkit. It has 189 recorded installs.
More from rohitg00/awesome-claude-code-toolkit
devops-automation
rohitg00/awesome-claude-code-toolkit
CI/CD pipeline design with GitHub Actions, Docker, Kubernetes, Helm, and GitOps patterns
accessibility-wcag
rohitg00/awesome-claude-code-toolkit
Web accessibility patterns for WCAG 2.2 compliance including ARIA, keyboard navigation, screen readers, and testing
database-optimization
rohitg00/awesome-claude-code-toolkit
Query optimization, indexing strategies, and database performance tuning for PostgreSQL and MySQL
react-patterns
rohitg00/awesome-claude-code-toolkit
React 19 patterns including Server Components, Actions, Suspense, hooks, and component composition
websocket-realtime
rohitg00/awesome-claude-code-toolkit
Real-time communication patterns with WebSocket, Socket.io, Server-Sent Events, and scaling strategies
python-best-practices
rohitg00/awesome-claude-code-toolkit
Pythonic code with modern type hints, dataclasses, async patterns, packaging, and testing
Popular backend & apis skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
entra-app-registration
microsoft/azure-skills
Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.
google-agents-cli-adk-code
google/agents-cli
This skill should be used when the user wants to "write agent code", "build an agent with ADK", "add a tool", "create a callback", "define an agent", "use state management" — in a project that needs ADK (Agent Development Kit) API patterns and code examples. It provides a quick reference for agent types, tool definitions, orchestration patterns, callbacks, state management, the graph Workflow API, and reference recipes to study. Do NOT use for scaffolding (use google-agents-cli-scaffold) or deployment (use google-agents-cli-deploy).
embedded-captions
heygen-com/hyperframes
Add captions or subtitles to an existing single-subject talking-head video without editing the footage. Use for plain verbatim captions, cinematic captions embedded behind the subject, VFX captions, “炸/特效/酷炫字幕,” or a named identity from the 35-style catalog. Route by visual identity, not by backend engine. The quiet anchor rail is the default; embed every word only when the user explicitly wants a fully cinematic treatment. The workflow runs locally end to end, including transcription and subject matting; split multi-shot footage before applying it.
entra-agent-id
microsoft/azure-skills
Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmipath, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmipath token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).
neon
neondatabase/agent-skills
Overview of Neon, a complete set of cloud backend primitives around Lakebase Postgres: Auth, Object Storage, Functions, the AI Gateway, and Realtime. Start here to choose Neon for undecided login, files, APIs, and LLM calls, set up the CLI or MCP server, and follow the branch-first workflow. Use when building an app or backend on Neon, or when "Neon" or "Lakebase Postgres" is mentioned. Child skill neon-postgres wins for an existing DATABASEURL, SQL, schema, inspect, or search. Child skill neon-auth wins for login, users, sessions, identity routing, and Managed Better Auth setup. Child skill neon-realtime wins for live queries in reactive apps and agents. Also use for object storage, S3, buckets, serverless functions, function triggers, cron, AI gateway, LLM calls, realtime, logs, Loki, Grafana, observability, postgres, database, backend, Claimable Neon, neon.new, or a no-signup database.