mcpField
G
go-ops

go-ops

github.com/0xdarkmatterDevelopment7851 installsUpdated 2w ago
Repository

About go-ops

A Go development reference skill covering idiomatic code, concurrency, testing, project structure, and performance. It offers quick guidance and deeper topic-specific references for Go developers.

Key features

  1. 01Idiomatic Go and error handling
  2. 02Concurrency patterns and guidance
  3. 03Interfaces and generics
  4. 04Testing and project structure
  5. 05Profiling and performance practices

Use cases

  1. 01Choosing an error-handling approach
  2. 02Designing concurrent Go tasks
  3. 03Structuring Go project packages
  4. 04Testing or profiling a Go project

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/0xdarkmatter/claude-mods --skill go-ops

After installing, type/go-opsin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

assets/
.gitkeep
references/
concurrency.md
error-handling.md
expert-insights.md
interfaces-generics.md
performance.md
project-structure.md
testing.md
scripts/
.gitkeep

Details

From the project README

Go Operations

Comprehensive Go skill covering idiomatic patterns, concurrency, and production practices.

Module Quick Start

# New module
go mod init github.com/user/project

# Add dependency
go get github.com/lib/pq@latest

# Tidy (remove unused, add missing)
go mod tidy

# Vendor dependencies
go mod vendor

# Workspace (multi-module)
go work init ./api ./shared
go work use ./cli

Error Handling Decision Tree

What kind of error?
│
├─ Known, expected condition (e.g. "not found")
│  └─ Sentinel error: var ErrNotFound = errors.New("not found")
│     └─ Caller checks: errors.Is(err, ErrNotFound)
│
├─ Need to carry structured data (status code, field name)
│  └─ Custom error type: type ValidationError struct { Field, Message string }
│     └─ Implement Error() string
│     └─ Caller checks: errors.As(err, &validErr)
│
├─ Adding context to an existing error
│  └─ Wrap: fmt.Errorf("load config: %w", err)
│     └─ Preserves original for Is/As checks
│
├─ Truly unrecoverable (corrupted state, programmer bug)
│  └─ panic("invariant violated: ...")
│     └─ Almost never in library code
│
└─ Multiple errors from concurrent work
   └─ errors.Join(err1, err2) or multierr package
Error Wrapping Convention
// Add context at each layer, don't repeat the function name
func LoadUser(id int) (*User, error) {
    row, err := db.Query("SELECT ...", id)
    if err != nil {
        return nil, fmt.Errorf("load user %d: %w", id, err)
    }
    // ...
}

Concurrency Decision Tree

What's the concurrency pattern?
│
├─ Run N independent tasks, collect results
│  └─ errgroup.Group (cancels on first error)
│
├─ Fire-and-forget background work
│  └─ go func() with context for cancellation
│     └─ ALWAYS handle the error or log it
│
├─ Producer/consumer pipeline
│  └─ Channels (buffered for throughput)
│     └─ Close channel when producer is done
│
├─ Rate-limited concurrent work
│  └─ Semaphore: make(chan struct{}, maxConcurrency)
│
├─ Shared mutable state
│  └─ sync.Mutex or sync.RWMutex
│     └─ Prefer channels if the state is simple
│
├─ One-time initialization
│  └─ sync.Once
│
└─ Wait for N goroutines to finish (no error collection)
   └─ sync.WaitGroup
errgroup Quick Start
import "golang.org/x/sync/errgroup"

g, ctx := errgroup.WithContext(ctx)
g.SetLimit(10) // max 10 concurrent goroutines

for _, url := range urls {
    g.Go(func() error {
        return fetch(ctx, url)
    })
}

if err := g.Wait(); err != nil {
    return fmt.Errorf("fetch urls: %w", err)
}

Deep dive: Load ./references/concurrency.md for worker pools, fan-out/fan-in, pipeline patterns, context best practices.

Interface Design

Accept interfaces, return structs.
// Good: function accepts interface
func Process(r io.Reader) error { ... }

// Good: return concrete type
func NewServer(cfg Config) *Server { ... }

// Bad: returning interface (hides implementation, prevents extension)
func NewServer(cfg Config) ServerInterface { ... }
Common Stdlib Interfaces
InterfaceMethodsUse For
io.ReaderRead([]byte) (int, error)Any byte source
io.WriterWrite([]byte) (int, error)Any byte sink
io.CloserClose() errorResource cleanup
fmt.StringerString() stringString representation
errorError() stringError values
sort.InterfaceLen, Less, SwapCustom sorting
http.HandlerServeHTTP(w, r)HTTP handlers
encoding.BinaryMarshalerMarshalBinary() ([]byte, error)Binary encoding
Functional Options Pattern
type Option func(*Server)

func WithPort(port int) Option {
    return func(s *Server) { s.port = port }
}

func WithTimeout(d time.Duration) Option {
    return func(s *Server) { s.timeout = d }
}

func NewServer(opts ...Option) *Server {
    s := &Server{port: 8080, timeout: 30 * time.Second} // defaults
    for _, opt := range opts {
        opt(s)
    }
    return s
}

// Usage
srv := NewServer(WithPort(9090), WithTimeout(5*time.Second))

Deep dive: Load ./references/interfaces-generics.md for generics, type constraints, embedding, type assertions.

Testing Quick Reference

// Table-driven test
func TestAdd(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"positive", 1, 2, 3},
        {"zero", 0, 0, 0},
        {"negative", -1, -2, -3},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got := Add(tt.a, tt.b)
            if got != tt.expected {
                t.Errorf("Add(%d, %d) = %d, want %d", tt.a, tt.b, got, tt.expected)
            }
        })
    }
}
# Run tests
go test ./...

# With coverage
go test -cover -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

# Run specific test
go test -run TestAdd ./pkg/math/

# Benchmarks
go test -bench=. -benchmem ./...

# Race detector
go test -race ./...

# Fuzz testing
go test -fuzz=FuzzParse ./...

Deep dive: Load ./references/testing.md for mocking with interfaces, httptest, testcontainers, golden files.

Common Gotchas

GotchaWhyFix
Nil slice vs empty slicevar s []int is nil, s := []int{} is empty. json.Marshal gives null vs []Use make([]int, 0) or []int{} if JSON matters
Goroutine leakGoroutine blocked on channel with no reader/writerUse context.WithCancel, always provide exit path
Defer in loopDeferred calls don't run until function returnsWrap loop body in a closure or use explicit cleanup
Interface nil pitfall(*MyType)(nil) assigned to error interface is not == nilReturn nil explicitly, not a nil typed pointer
Range variable captureLoop var reused (pre-Go 1.22)Use go func(v T) { ... }(v) or upgrade to Go 1.22+
String concatenation in loopO(n^2) allocationUse strings.Builder
sync.WaitGroup Add after GoRace conditionCall wg.Add(1) before go func()
Unbuffered channel deadlockSend/receive must happen concurrentlyUse buffered channel or separate goroutines
map not safe for concurrent useRace condition, may crashUse sync.Mutex or sync.Map

Project Structure

project/
├── cmd/
│   ├── api/main.go           # Entry points
│   └── worker/main.go
├── internal/                  # Private packages
│   ├── handler/
│   ├── service/
│   └── repository/
├── pkg/                       # Public packages (optional)
├── go.mod
├── go.sum
├── Makefile                   # or justfile
└── .golangci.yml

Deep dive: Load ./references/project-structure.md for workspace mode, build tags, ldflags, linting config.

Performance Quick Reference

# CPU profile
go test -cpuprofile=cpu.prof -bench=. ./...
go tool pprof cpu.prof

# Memory profile
go test -memprofile=mem.prof -bench=. ./...
go tool pprof -alloc_space mem.prof

# Trace
go test -trace=trace.out ./...
go tool trace trace.out

# Escape analysis
go build -gcflags='-m' ./...
OptimizationWhenPattern
Pre-allocate slicesKnown sizemake([]T, 0, n)
strings.BuilderString concatenationvar b strings.Builder
sync.PoolFrequent alloc/free of same typepool.Get() / pool.Put()
Struct field alignmentMemory-sensitiveGroup fields by size (largest first)
Buffer reuseI/O-heavybufio.NewReaderSize(r, 64*1024)

Deep dive: Load ./references/performance.md for pprof walkthrough, benchmarking patterns, escape analysis.

Reference Files

Load these for deep-dive topics. Each is self-contained.

ReferenceWhen to Load
./references/concurrency.mdGoroutines, channels, context, sync primitives, worker pools, pipelines
./references/error-handling.mdError wrapping, sentinel errors, custom types, multi-error, panic/recover
./references/testing.mdTable tests, mocking, httptest, benchmarks, fuzz, testcontainers, golden files
./references/interfaces-generics.mdInterface design, embedding, type assertions, generics, type constraints
./references/project-structure.mdStandard layout, go.mod, workspaces, build tags, ldflags, golangci-lint
./references/performance.mdpprof, trace, benchmarks, escape analysis, sync.Pool, struct alignment
./references/expert-insights.mdHTTP server (Go 1.22 routing), graceful shutdown, http.Client tuning, JSON helpers

See Also

  • docker-ops - Multi-stage builds for Go binaries (scratch/distroless)
  • ci-cd-ops - Go CI pipelines, caching go modules, goreleaser
  • testing-ops - Cross-language testing strategies

Comments

Markdown supported