Get the FREE Ultimate OpenClaw Setup Guide →

go-best-practices

Scanned
npx machina-cli add skill Taoidle/plan-cascade/go --openclaw
Files (1)
SKILL.md
2.1 KB

Go Best Practices

Code Style

RuleGuideline
Formattergofmt or goimports
Lintergolangci-lint
NamingShort, clear; avoid stuttering
CommentsGodoc for exported items

Error Handling

RuleGuideline
Always checkNever ignore errors
Wrap contextfmt.Errorf("ctx: %w", err)
Sentinel errorsvar ErrNotFound = errors.New(...)
func Load(path string) (*Config, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return nil, fmt.Errorf("load config %s: %w", path, err)
    }
    // ...
}

Project Structure

cmd/appname/main.go
internal/config/
internal/service/
go.mod

Concurrency

PatternUsage
context.ContextCancellation, timeouts
sync.WaitGroupWait for goroutines
errgroup.GroupGoroutines with errors
func Process(ctx context.Context, items []Item) error {
    for _, item := range items {
        select {
        case <-ctx.Done():
            return ctx.Err()
        default:
            if err := process(item); err != nil { return err }
        }
    }
    return nil
}

Anti-Patterns

AvoidUse Instead
Naked returnsExplicit returns
panic for errorsReturn errors
Large interfacesSmall, focused
init()Explicit init

Testing (Table-Driven)

func TestParse(t *testing.T) {
    tests := []struct{ name, input string; want int; wantErr bool }{
        {"valid", "42", 42, false},
        {"invalid", "abc", 0, true},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := Parse(tt.input)
            if (err != nil) != tt.wantErr { t.Errorf("err=%v, want=%v", err, tt.wantErr) }
            if got != tt.want { t.Errorf("got=%v, want=%v", got, tt.want) }
        })
    }
}

Source

git clone https://github.com/Taoidle/plan-cascade/blob/master/builtin-skills/go/SKILL.mdView on GitHub

Overview

Go Best Practices covers error handling, concurrency, and idiomatic patterns to help you write and review robust Go code. It emphasizes consistent style, meaningful error propagation, and safe concurrent execution.

How This Skill Works

It defines concrete rules for error handling (always check errors, wrap with %w for context, use sentinel errors) and prescribes idiomatic concurrency using context.Context, sync.WaitGroup, and errgroup. It also covers project structure, naming, and documentation conventions to promote readability.

When to Use It

  • When starting a new Go project to set conventions.
  • During code reviews to enforce consistency and idioms.
  • When refactoring error handling to avoid ignored errors.
  • When implementing concurrent tasks with proper cancellation.
  • When writing or updating tests, especially table-driven tests.

Quick Start

  1. Step 1: Format and lint your code with gofmt, goimports, and golangci-lint.
  2. Step 2: Review and wrap errors; avoid ignoring them.
  3. Step 3: Adopt safe concurrency with context, WaitGroup or errgroup; fix anti-patterns.

Best Practices

  • Format with gofmt and goimports; lint with golangci-lint.
  • Name succinctly; provide Godoc for exported items.
  • Always check and wrap errors; use sentinel errors.
  • Use context.Context for cancellation and timeouts; choose appropriate concurrency primitives (WaitGroup or errgroup).
  • Avoid anti-patterns: naked returns, panics, large interfaces, and init; keep code and packages well-structured.

Example Use Cases

  • Load demonstrates wrapping errors with context by using fmt.Errorf and %w.
  • Process shows cancellation with a context and early return on ctx.Err().
  • Sentinel error pattern with defined ErrNotFound for domain errors.
  • Table-driven tests pattern as seen in TestParse.
  • Using errgroup to run concurrent tasks and propagate errors.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers