golang-patterns — ai-agents golang-patterns, everything-claude-code, official, ai-agents, ide skills, anthropic, claude-code, developer-tools, Claude Code, Cursor, Windsurf

Verified
v1.0.0
GitHub

About this Skill

Perfect for Code Analysis Agents needing to enforce idiomatic Go patterns and best practices. Idiomatic Go patterns, best practices, and conventions for building robust, efficient, and maintainable Go applications.

# Core Topics

affaan-m affaan-m
[60.6k]
[7501]
Updated: 3/5/2026

Agent Capability Analysis

The golang-patterns skill by affaan-m is an open-source official AI agent skill for Claude Code and other IDE workflows, helping agents execute tasks with better context, repeatability, and domain-specific guidance. Optimized for ai-agents, anthropic, claude-code.

Ideal Agent Persona

Perfect for Code Analysis Agents needing to enforce idiomatic Go patterns and best practices.

Core Value

Enables agents to analyze, generate, and refactor Go code according to established conventions like simplicity, error handling patterns, and concurrency models. Provides immediate access to idiomatic solutions for common Go development scenarios.

Capabilities Granted for golang-patterns

Reviewing Go code for idiomatic patterns
Refactoring existing Go applications
Designing new Go packages/modules
Implementing concurrent Go routines safely
Optimizing Go error handling strategies

! Prerequisites & Limits

  • Go-specific patterns only
  • Requires understanding of Go syntax
  • Focuses on conventions rather than syntax validation
Labs Demo

Browser Sandbox Environment

⚡️ Ready to unleash?

Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.

Boot Container Sandbox

golang-patterns

Install golang-patterns, an AI agent skill for AI agent workflows and automation. Works with Claude Code, Cursor, and Windsurf with one-command setup.

SKILL.md
Readonly

Go Development Patterns

Idiomatic Go patterns and best practices for building robust, efficient, and maintainable applications.

When to Activate

  • Writing new Go code
  • Reviewing Go code
  • Refactoring existing Go code
  • Designing Go packages/modules

Core Principles

1. Simplicity and Clarity

Go favors simplicity over cleverness. Code should be obvious and easy to read.

go
1// Good: Clear and direct 2func GetUser(id string) (*User, error) { 3 user, err := db.FindUser(id) 4 if err != nil { 5 return nil, fmt.Errorf("get user %s: %w", id, err) 6 } 7 return user, nil 8} 9 10// Bad: Overly clever 11func GetUser(id string) (*User, error) { 12 return func() (*User, error) { 13 if u, e := db.FindUser(id); e == nil { 14 return u, nil 15 } else { 16 return nil, e 17 } 18 }() 19}

2. Make the Zero Value Useful

Design types so their zero value is immediately usable without initialization.

go
1// Good: Zero value is useful 2type Counter struct { 3 mu sync.Mutex 4 count int // zero value is 0, ready to use 5} 6 7func (c *Counter) Inc() { 8 c.mu.Lock() 9 c.count++ 10 c.mu.Unlock() 11} 12 13// Good: bytes.Buffer works with zero value 14var buf bytes.Buffer 15buf.WriteString("hello") 16 17// Bad: Requires initialization 18type BadCounter struct { 19 counts map[string]int // nil map will panic 20}

3. Accept Interfaces, Return Structs

Functions should accept interface parameters and return concrete types.

go
1// Good: Accepts interface, returns concrete type 2func ProcessData(r io.Reader) (*Result, error) { 3 data, err := io.ReadAll(r) 4 if err != nil { 5 return nil, err 6 } 7 return &Result{Data: data}, nil 8} 9 10// Bad: Returns interface (hides implementation details unnecessarily) 11func ProcessData(r io.Reader) (io.Reader, error) { 12 // ... 13}

Error Handling Patterns

Error Wrapping with Context

go
1// Good: Wrap errors with context 2func LoadConfig(path string) (*Config, error) { 3 data, err := os.ReadFile(path) 4 if err != nil { 5 return nil, fmt.Errorf("load config %s: %w", path, err) 6 } 7 8 var cfg Config 9 if err := json.Unmarshal(data, &cfg); err != nil { 10 return nil, fmt.Errorf("parse config %s: %w", path, err) 11 } 12 13 return &cfg, nil 14}

Custom Error Types

go
1// Define domain-specific errors 2type ValidationError struct { 3 Field string 4 Message string 5} 6 7func (e *ValidationError) Error() string { 8 return fmt.Sprintf("validation failed on %s: %s", e.Field, e.Message) 9} 10 11// Sentinel errors for common cases 12var ( 13 ErrNotFound = errors.New("resource not found") 14 ErrUnauthorized = errors.New("unauthorized") 15 ErrInvalidInput = errors.New("invalid input") 16)

Error Checking with errors.Is and errors.As

go
1func HandleError(err error) { 2 // Check for specific error 3 if errors.Is(err, sql.ErrNoRows) { 4 log.Println("No records found") 5 return 6 } 7 8 // Check for error type 9 var validationErr *ValidationError 10 if errors.As(err, &validationErr) { 11 log.Printf("Validation error on field %s: %s", 12 validationErr.Field, validationErr.Message) 13 return 14 } 15 16 // Unknown error 17 log.Printf("Unexpected error: %v", err) 18}

Never Ignore Errors

go
1// Bad: Ignoring error with blank identifier 2result, _ := doSomething() 3 4// Good: Handle or explicitly document why it's safe to ignore 5result, err := doSomething() 6if err != nil { 7 return err 8} 9 10// Acceptable: When error truly doesn't matter (rare) 11_ = writer.Close() // Best-effort cleanup, error logged elsewhere

Concurrency Patterns

Worker Pool

go
1func WorkerPool(jobs <-chan Job, results chan<- Result, numWorkers int) { 2 var wg sync.WaitGroup 3 4 for i := 0; i < numWorkers; i++ { 5 wg.Add(1) 6 go func() { 7 defer wg.Done() 8 for job := range jobs { 9 results <- process(job) 10 } 11 }() 12 } 13 14 wg.Wait() 15 close(results) 16}

Context for Cancellation and Timeouts

go
1func FetchWithTimeout(ctx context.Context, url string) ([]byte, error) { 2 ctx, cancel := context.WithTimeout(ctx, 5*time.Second) 3 defer cancel() 4 5 req, err := http.NewRequestWithContext(ctx, "GET", url, nil) 6 if err != nil { 7 return nil, fmt.Errorf("create request: %w", err) 8 } 9 10 resp, err := http.DefaultClient.Do(req) 11 if err != nil { 12 return nil, fmt.Errorf("fetch %s: %w", url, err) 13 } 14 defer resp.Body.Close() 15 16 return io.ReadAll(resp.Body) 17}

Graceful Shutdown

go
1func GracefulShutdown(server *http.Server) { 2 quit := make(chan os.Signal, 1) 3 signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) 4 5 <-quit 6 log.Println("Shutting down server...") 7 8 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 9 defer cancel() 10 11 if err := server.Shutdown(ctx); err != nil { 12 log.Fatalf("Server forced to shutdown: %v", err) 13 } 14 15 log.Println("Server exited") 16}

errgroup for Coordinated Goroutines

go
1import "golang.org/x/sync/errgroup" 2 3func FetchAll(ctx context.Context, urls []string) ([][]byte, error) { 4 g, ctx := errgroup.WithContext(ctx) 5 results := make([][]byte, len(urls)) 6 7 for i, url := range urls { 8 i, url := i, url // Capture loop variables 9 g.Go(func() error { 10 data, err := FetchWithTimeout(ctx, url) 11 if err != nil { 12 return err 13 } 14 results[i] = data 15 return nil 16 }) 17 } 18 19 if err := g.Wait(); err != nil { 20 return nil, err 21 } 22 return results, nil 23}

Avoiding Goroutine Leaks

go
1// Bad: Goroutine leak if context is cancelled 2func leakyFetch(ctx context.Context, url string) <-chan []byte { 3 ch := make(chan []byte) 4 go func() { 5 data, _ := fetch(url) 6 ch <- data // Blocks forever if no receiver 7 }() 8 return ch 9} 10 11// Good: Properly handles cancellation 12func safeFetch(ctx context.Context, url string) <-chan []byte { 13 ch := make(chan []byte, 1) // Buffered channel 14 go func() { 15 data, err := fetch(url) 16 if err != nil { 17 return 18 } 19 select { 20 case ch <- data: 21 case <-ctx.Done(): 22 } 23 }() 24 return ch 25}

Interface Design

Small, Focused Interfaces

go
1// Good: Single-method interfaces 2type Reader interface { 3 Read(p []byte) (n int, err error) 4} 5 6type Writer interface { 7 Write(p []byte) (n int, err error) 8} 9 10type Closer interface { 11 Close() error 12} 13 14// Compose interfaces as needed 15type ReadWriteCloser interface { 16 Reader 17 Writer 18 Closer 19}

Define Interfaces Where They're Used

go
1// In the consumer package, not the provider 2package service 3 4// UserStore defines what this service needs 5type UserStore interface { 6 GetUser(id string) (*User, error) 7 SaveUser(user *User) error 8} 9 10type Service struct { 11 store UserStore 12} 13 14// Concrete implementation can be in another package 15// It doesn't need to know about this interface

Optional Behavior with Type Assertions

go
1type Flusher interface { 2 Flush() error 3} 4 5func WriteAndFlush(w io.Writer, data []byte) error { 6 if _, err := w.Write(data); err != nil { 7 return err 8 } 9 10 // Flush if supported 11 if f, ok := w.(Flusher); ok { 12 return f.Flush() 13 } 14 return nil 15}

Package Organization

Standard Project Layout

text
1myproject/ 2├── cmd/ 3│ └── myapp/ 4│ └── main.go # Entry point 5├── internal/ 6│ ├── handler/ # HTTP handlers 7│ ├── service/ # Business logic 8│ ├── repository/ # Data access 9│ └── config/ # Configuration 10├── pkg/ 11│ └── client/ # Public API client 12├── api/ 13│ └── v1/ # API definitions (proto, OpenAPI) 14├── testdata/ # Test fixtures 15├── go.mod 16├── go.sum 17└── Makefile

Package Naming

go
1// Good: Short, lowercase, no underscores 2package http 3package json 4package user 5 6// Bad: Verbose, mixed case, or redundant 7package httpHandler 8package json_parser 9package userService // Redundant 'Service' suffix

Avoid Package-Level State

go
1// Bad: Global mutable state 2var db *sql.DB 3 4func init() { 5 db, _ = sql.Open("postgres", os.Getenv("DATABASE_URL")) 6} 7 8// Good: Dependency injection 9type Server struct { 10 db *sql.DB 11} 12 13func NewServer(db *sql.DB) *Server { 14 return &Server{db: db} 15}

Struct Design

Functional Options Pattern

go
1type Server struct { 2 addr string 3 timeout time.Duration 4 logger *log.Logger 5} 6 7type Option func(*Server) 8 9func WithTimeout(d time.Duration) Option { 10 return func(s *Server) { 11 s.timeout = d 12 } 13} 14 15func WithLogger(l *log.Logger) Option { 16 return func(s *Server) { 17 s.logger = l 18 } 19} 20 21func NewServer(addr string, opts ...Option) *Server { 22 s := &Server{ 23 addr: addr, 24 timeout: 30 * time.Second, // default 25 logger: log.Default(), // default 26 } 27 for _, opt := range opts { 28 opt(s) 29 } 30 return s 31} 32 33// Usage 34server := NewServer(":8080", 35 WithTimeout(60*time.Second), 36 WithLogger(customLogger), 37)

Embedding for Composition

go
1type Logger struct { 2 prefix string 3} 4 5func (l *Logger) Log(msg string) { 6 fmt.Printf("[%s] %s\n", l.prefix, msg) 7} 8 9type Server struct { 10 *Logger // Embedding - Server gets Log method 11 addr string 12} 13 14func NewServer(addr string) *Server { 15 return &Server{ 16 Logger: &Logger{prefix: "SERVER"}, 17 addr: addr, 18 } 19} 20 21// Usage 22s := NewServer(":8080") 23s.Log("Starting...") // Calls embedded Logger.Log

Memory and Performance

Preallocate Slices When Size is Known

go
1// Bad: Grows slice multiple times 2func processItems(items []Item) []Result { 3 var results []Result 4 for _, item := range items { 5 results = append(results, process(item)) 6 } 7 return results 8} 9 10// Good: Single allocation 11func processItems(items []Item) []Result { 12 results := make([]Result, 0, len(items)) 13 for _, item := range items { 14 results = append(results, process(item)) 15 } 16 return results 17}

Use sync.Pool for Frequent Allocations

go
1var bufferPool = sync.Pool{ 2 New: func() interface{} { 3 return new(bytes.Buffer) 4 }, 5} 6 7func ProcessRequest(data []byte) []byte { 8 buf := bufferPool.Get().(*bytes.Buffer) 9 defer func() { 10 buf.Reset() 11 bufferPool.Put(buf) 12 }() 13 14 buf.Write(data) 15 // Process... 16 return buf.Bytes() 17}

Avoid String Concatenation in Loops

go
1// Bad: Creates many string allocations 2func join(parts []string) string { 3 var result string 4 for _, p := range parts { 5 result += p + "," 6 } 7 return result 8} 9 10// Good: Single allocation with strings.Builder 11func join(parts []string) string { 12 var sb strings.Builder 13 for i, p := range parts { 14 if i > 0 { 15 sb.WriteString(",") 16 } 17 sb.WriteString(p) 18 } 19 return sb.String() 20} 21 22// Best: Use standard library 23func join(parts []string) string { 24 return strings.Join(parts, ",") 25}

Go Tooling Integration

Essential Commands

bash
1# Build and run 2go build ./... 3go run ./cmd/myapp 4 5# Testing 6go test ./... 7go test -race ./... 8go test -cover ./... 9 10# Static analysis 11go vet ./... 12staticcheck ./... 13golangci-lint run 14 15# Module management 16go mod tidy 17go mod verify 18 19# Formatting 20gofmt -w . 21goimports -w .
yaml
1linters: 2 enable: 3 - errcheck 4 - gosimple 5 - govet 6 - ineffassign 7 - staticcheck 8 - unused 9 - gofmt 10 - goimports 11 - misspell 12 - unconvert 13 - unparam 14 15linters-settings: 16 errcheck: 17 check-type-assertions: true 18 govet: 19 check-shadowing: true 20 21issues: 22 exclude-use-default: false

Quick Reference: Go Idioms

IdiomDescription
Accept interfaces, return structsFunctions accept interface params, return concrete types
Errors are valuesTreat errors as first-class values, not exceptions
Don't communicate by sharing memoryUse channels for coordination between goroutines
Make the zero value usefulTypes should work without explicit initialization
A little copying is better than a little dependencyAvoid unnecessary external dependencies
Clear is better than cleverPrioritize readability over cleverness
gofmt is no one's favorite but everyone's friendAlways format with gofmt/goimports
Return earlyHandle errors first, keep happy path unindented

Anti-Patterns to Avoid

go
1// Bad: Naked returns in long functions 2func process() (result int, err error) { 3 // ... 50 lines ... 4 return // What is being returned? 5} 6 7// Bad: Using panic for control flow 8func GetUser(id string) *User { 9 user, err := db.Find(id) 10 if err != nil { 11 panic(err) // Don't do this 12 } 13 return user 14} 15 16// Bad: Passing context in struct 17type Request struct { 18 ctx context.Context // Context should be first param 19 ID string 20} 21 22// Good: Context as first parameter 23func ProcessRequest(ctx context.Context, id string) error { 24 // ... 25} 26 27// Bad: Mixing value and pointer receivers 28type Counter struct{ n int } 29func (c Counter) Value() int { return c.n } // Value receiver 30func (c *Counter) Increment() { c.n++ } // Pointer receiver 31// Pick one style and be consistent

Remember: Go code should be boring in the best way - predictable, consistent, and easy to understand. When in doubt, keep it simple.

FAQ & Installation Steps

These questions and steps mirror the structured data on this page for better search understanding.

? Frequently Asked Questions

What is golang-patterns?

Perfect for Code Analysis Agents needing to enforce idiomatic Go patterns and best practices. Idiomatic Go patterns, best practices, and conventions for building robust, efficient, and maintainable Go applications.

How do I install golang-patterns?

Run the command: npx killer-skills add affaan-m/everything-claude-code/golang-patterns. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.

What are the use cases for golang-patterns?

Key use cases include: Reviewing Go code for idiomatic patterns, Refactoring existing Go applications, Designing new Go packages/modules, Implementing concurrent Go routines safely, Optimizing Go error handling strategies.

Which IDEs are compatible with golang-patterns?

This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.

Are there any limitations for golang-patterns?

Go-specific patterns only. Requires understanding of Go syntax. Focuses on conventions rather than syntax validation.

How To Install

  1. 1. Open your terminal

    Open the terminal or command line in your project directory.

  2. 2. Run the install command

    Run: npx killer-skills add affaan-m/everything-claude-code/golang-patterns. The CLI will automatically detect your IDE or AI agent and configure the skill.

  3. 3. Start using the skill

    The skill is now active. Your AI agent can use golang-patterns immediately in the current project.

Related Skills

Looking for an alternative to golang-patterns or another official skill for your workflow? Explore these related open-source skills.

View All

flags

Logo of facebook
facebook

Use when you need to check feature flag states, compare channels, or debug why a feature behaves differently across release channels.

243.6k
0
Developer

extract-errors

Logo of facebook
facebook

Use when adding new error messages to React, or seeing unknown error code warnings.

243.6k
0
Developer

fix

Logo of facebook
facebook

Use when you have lint errors, formatting issues, or before committing code to ensure it passes CI.

243.6k
0
Developer

flow

Logo of facebook
facebook

Use when you need to run Flow type checking, or when seeing Flow type errors in React code.

243.6k
0
Developer