🎯

go-best-practices

🎯Skill

from 0xbigboss/claude-code

VibeIndex|
What it does

Enforces type-first Go development with custom types, interfaces, and patterns to create robust, self-documenting code with strong compile-time guarantees.

go-best-practices

Installation

Install skill:
npx skills add https://github.com/0xbigboss/claude-code --skill go-best-practices
40
AddedJan 27, 2026

Skill Details

SKILL.md

Provides Go patterns for type-first development with custom types, interfaces, functional options, and error handling. Must use when reading or writing Go files.

Overview

# Go Best Practices

Type-First Development

Types define the contract before implementation. Follow this workflow:

  1. Define data structures - structs and interfaces first
  2. Define function signatures - parameters, return types, and error conditions
  3. Implement to satisfy types - let the compiler guide completeness
  4. Validate at boundaries - check inputs where data enters the system

Make Illegal States Unrepresentable

Use Go's type system to prevent invalid states at compile time.

Structs for domain models:

```go

// Define the data model first

type User struct {

ID UserID

Email string

Name string

CreatedAt time.Time

}

type CreateUserRequest struct {

Email string

Name string

}

// Functions follow from the types

func CreateUser(req CreateUserRequest) (*User, error) {

// implementation

}

```

Custom types for domain primitives:

```go

// Distinct types prevent mixing up IDs

type UserID string

type OrderID string

func GetUser(id UserID) (*User, error) {

// Compiler prevents passing OrderID here

}

func NewUserID(raw string) UserID {

return UserID(raw)

}

// Methods attach behavior to the type

func (id UserID) String() string {

return string(id)

}

```

Interfaces for behavior contracts:

```go

// Define what you need, not what you have

type Reader interface {

Read(p []byte) (n int, err error)

}

type UserRepository interface {

GetByID(ctx context.Context, id UserID) (*User, error)

Save(ctx context.Context, user *User) error

}

// Accept interfaces, return structs

func ProcessInput(r Reader) ([]byte, error) {

return io.ReadAll(r)

}

```

Enums with iota:

```go

type Status int

const (

StatusActive Status = iota + 1

StatusInactive

StatusPending

)

func (s Status) String() string {

switch s {

case StatusActive:

return "active"

case StatusInactive:

return "inactive"

case StatusPending:

return "pending"

default:

return fmt.Sprintf("Status(%d)", s)

}

}

// Exhaustive handling in switch

func ProcessStatus(s Status) (string, error) {

switch s {

case StatusActive:

return "processing", nil

case StatusInactive:

return "skipped", nil

case StatusPending:

return "waiting", nil

default:

return "", fmt.Errorf("unhandled status: %v", s)

}

}

```

Functional options for flexible construction:

```go

type ServerOption func(*Server)

func WithPort(port int) ServerOption {

return func(s *Server) {

s.port = port

}

}

func WithTimeout(d time.Duration) ServerOption {

return func(s *Server) {

s.timeout = d

}

}

func NewServer(opts ...ServerOption) *Server {

s := &Server{

port: 8080, // sensible defaults

timeout: 30 * time.Second,

}

for _, opt := range opts {

opt(s)

}

return s

}

// Usage: NewServer(WithPort(3000), WithTimeout(time.Minute))

```

Embed for composition:

```go

type Timestamps struct {

CreatedAt time.Time

UpdatedAt time.Time

}

type User struct {

Timestamps // embedded - User has CreatedAt, UpdatedAt

ID UserID

Email string

}

```

Module Structure

Prefer smaller files within packages: one type or concern per file. Split when a file handles multiple unrelated types or exceeds ~300 lines. Keep tests in _test.go files alongside implementation. Package boundaries define the API; internal organization is flexible.

Functional Patterns

  • Use value receivers when methods don't mutate state; reserve pointer receivers for mutation.
  • Avoid package-level mutable variables; pass dependencies explicitly via function parameters.
  • Return new structs/slices rather than mutating inputs; makes data flow explicit.
  • Use closures and higher-order functions where they simplify code (e.g., sort.Slice, iterators).

Instructions

  • Return errors with context using fmt.Errorf and %w for wrapping. This preserves the error chain for debugging.
  • Every function returns a value or an error; unimplemented paths return descriptive errors. Explicit failures are debuggable.
  • Handle all branches in switch statements; include a default case that returns an error. Exhaustive handling prevents silent bugs.
  • Pass context.Context to external calls with explicit timeouts. Runaway requests cause cascading failures.
  • Reserve panic for truly unrecoverable situations; prefer returning errors. Panics crash the program.
  • Add or update table-driven tests for new logic; cover edge cases (empty input, nil, boundaries).

Examples

Explicit failure for unimplemented logic:

```go

func buildWidget(widgetType string) (*Widget, error) {

return nil, fmt.Errorf("buildWidget not implemented for type: %s", widgetType)

}

```

Wrap errors with context to preserve the chain:

```go

out, err := client.Do(ctx, req)

if err != nil {

return nil, fmt.Errorf("fetch widget failed: %w", err)

}

return out, nil

```

Exhaustive switch with default error:

```go

func processStatus(status string) (string, error) {

switch status {

case "active":

return "processing", nil

case "inactive":

return "skipped", nil

default:

return "", fmt.Errorf("unhandled status: %s", status)

}

}

```

Structured logging with slog:

```go

import "log/slog"

var log = slog.With("component", "widgets")

func createWidget(name string) (*Widget, error) {

log.Debug("creating widget", "name", name)

widget := &Widget{Name: name}

log.Debug("created widget", "id", widget.ID)

return widget, nil

}

```

Configuration

  • Load config from environment variables at startup; validate required values before use. Missing config should cause immediate exit.
  • Define a Config struct as single source of truth; avoid os.Getenv scattered throughout code.
  • Use sensible defaults for development; require explicit values for production secrets.

Examples

Typed config struct:

```go

type Config struct {

Port int

DatabaseURL string

APIKey string

Env string

}

func LoadConfig() (*Config, error) {

dbURL := os.Getenv("DATABASE_URL")

if dbURL == "" {

return nil, fmt.Errorf("DATABASE_URL is required")

}

apiKey := os.Getenv("API_KEY")

if apiKey == "" {

return nil, fmt.Errorf("API_KEY is required")

}

port := 3000

if p := os.Getenv("PORT"); p != "" {

var err error

port, err = strconv.Atoi(p)

if err != nil {

return nil, fmt.Errorf("invalid PORT: %w", err)

}

}

return &Config{

Port: port,

DatabaseURL: dbURL,

APIKey: apiKey,

Env: getEnvOrDefault("ENV", "development"),

}, nil

}

```

More from this repository10

🎯
react-best-practices🎯Skill

Guides React developers in writing clean, efficient components by providing best practices for hooks, effects, and component design.

🎯
python-best-practices🎯Skill

Guides Python developers in implementing type-first development with robust type checking, dataclasses, discriminated unions, and domain-specific type primitives.

🎯
openai-image-gen🎯Skill

Generates images using OpenAI's image generation API within the Claude Code environment.

🎯
tamagui-best-practices🎯Skill

Optimizes Tamagui configurations and styling patterns for high-performance, cross-platform React Native and web applications with v4 compiler settings.

🎯
playwright-best-practices🎯Skill

Provides Playwright test best practices for creating resilient, maintainable tests using user-facing locators, Page Object Models, and robust testing patterns.

🎯
web-fetch🎯Skill

Fetches web content and converts HTML to clean markdown using intelligent content extraction and CSS selectors.

🎯
zig-best-practices🎯Skill

Enforces type-first development in Zig by leveraging tagged unions, explicit error sets, comptime validation, and type safety techniques.

🎯
typescript-best-practices🎯Skill

Enforces TypeScript best practices by guiding developers to create robust, type-safe code through compile-time validation, discriminated unions, and explicit type definitions.

🎯
ios-device-screenshot🎯Skill

Captures screenshots from physical iOS devices connected via USB using pymobiledevice3, supporting iOS versions 16 and 17+.

🎯
gen-env🎯Skill

Generates environment configuration files or environment variables for development projects, ensuring consistent and reproducible setup across different environments.