standards-golang
npx skills add https://github.com/maxritter/claude-pilot --skill standards-golang
Agent 安装分布
Skill 文档
Go Standards
Core Rule: Use Go modules for dependencies, go test for testing, gofmt + go vet + golangci-lint for quality. Write idiomatic Go with explicit error handling.
When to use this skill
- When creating or managing Go modules and dependencies
- When writing or running tests in Go projects
- When formatting Go code or fixing linting issues
- When implementing error handling patterns
- When organizing package structure
- When deciding whether to create a new Go file or extend existing ones
- When setting up code quality checks (formatting, vetting, linting)
- When ensuring code follows Go idioms and best practices
Module Management
Use Go modules for all dependency management:
# Initialize a new module
go mod init github.com/org/project
# Dependencies are added automatically via imports
# Then run tidy to update go.mod and go.sum
go mod tidy
# Update all dependencies
go get -u ./...
# Update specific dependency
go get -u github.com/pkg/name@latest
# Verify dependencies
go mod verify
# Clean module cache
go clean -modcache
Module file structure:
go.mod– Module definition and direct dependenciesgo.sum– Cryptographic checksums for dependencies
Testing with go test
Run tests using standard go test:
go test ./... # All tests
go test ./pkg/... # Tests in pkg/ and subdirs
go test -v ./... # Verbose output (debugging only)
go test -short ./... # Skip long-running tests
go test -race ./... # With race detector
go test -cover ./... # With coverage summary
go test -coverprofile=coverage.out ./... # Generate coverage file
go tool cover -html=coverage.out # View coverage in browser
Test file naming: Tests go in *_test.go files alongside the code they test.
Test function naming: func TestFunctionName(t *testing.T)
func TestProcessOrder(t *testing.T) {
order := Order{ID: "123", Amount: 100}
result, err := ProcessOrder(order)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result.Status != "completed" {
t.Errorf("got status %q, want %q", result.Status, "completed")
}
}
Table-driven tests: Preferred for testing multiple cases:
func TestValidateEmail(t *testing.T) {
tests := []struct {
name string
email string
wantErr bool
}{
{"valid email", "user@example.com", false},
{"missing @", "userexample.com", true},
{"empty", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := ValidateEmail(tt.email)
if (err != nil) != tt.wantErr {
t.Errorf("ValidateEmail(%q) error = %v, wantErr %v", tt.email, err, tt.wantErr)
}
})
}
}
Code Quality Tools
Formatting with gofmt:
gofmt -w . # Format all Go files in place
gofmt -d . # Show diff without modifying
goimports -w . # Format + organize imports
Static analysis with go vet:
go vet ./... # Check for common mistakes
Comprehensive linting with golangci-lint:
golangci-lint run # Run all enabled linters
golangci-lint run --fix # Auto-fix where possible
golangci-lint run --fast # Quick check (fewer linters)
Run quality checks before marking work complete.
Error Handling
Always handle errors explicitly. Never ignore them.
// REQUIRED - handle the error
result, err := doSomething()
if err != nil {
return fmt.Errorf("doing something: %w", err)
}
// FORBIDDEN - ignoring errors
result, _ := doSomething() // Never do this
Error wrapping: Add context when propagating errors:
func ProcessUser(userID string) error {
user, err := fetchUser(userID)
if err != nil {
return fmt.Errorf("fetching user %s: %w", userID, err)
}
if err := validateUser(user); err != nil {
return fmt.Errorf("validating user %s: %w", userID, err)
}
return nil
}
Custom errors: Use for domain-specific error types:
var ErrNotFound = errors.New("not found")
var ErrInvalidInput = errors.New("invalid input")
// Check with errors.Is
if errors.Is(err, ErrNotFound) {
// handle not found
}
Code Style
Naming conventions:
| Type | Convention | Example |
|---|---|---|
| Packages | lowercase, single word | http, json, user |
| Exported | PascalCase | ProcessOrder, UserService |
| Unexported | camelCase | processOrder, userService |
| Acronyms | ALL CAPS | HTTPServer, XMLParser, ID |
| Interfaces | -er suffix (often) | Reader, Writer, Handler |
Comments for exported functions:
// ProcessOrder validates and processes the given order.
// It returns ErrInvalidOrder if the order is malformed.
func ProcessOrder(order Order) error {
// implementation
}
Import organization: Standard library, then third-party, then local:
import (
"context"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"github.com/myorg/myproject/internal/service"
)
Common Patterns
Context propagation: Always pass context as first parameter:
func ProcessRequest(ctx context.Context, req Request) (Response, error) {
// Use ctx for cancellation, timeouts, and request-scoped values
result, err := db.QueryContext(ctx, query)
if err != nil {
return Response{}, err
}
return Response{Data: result}, nil
}
Defer for cleanup:
func ReadFile(path string) ([]byte, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close() // Guaranteed to run on function exit
return io.ReadAll(f)
}
Struct initialization:
// Named fields (preferred for clarity)
user := User{
ID: "123",
Name: "Alice",
Email: "alice@example.com",
}
// Zero values are valid - use them
var count int // 0
var name string // ""
var items []string // nil (valid for append)
File Organization
Prefer editing existing files over creating new ones.
Before creating a new Go file, ask:
- Can this fit in an existing package?
- Is there a related file to extend?
- Does this truly need to be separate?
Standard project structure:
project/
âââ cmd/ # Main applications
â âââ server/
â âââ main.go
âââ internal/ # Private packages (can't be imported externally)
â âââ handler/
â âââ service/
â âââ repository/
âââ pkg/ # Public packages (can be imported)
â âââ api/
âââ go.mod
âââ go.sum
Verification Checklist
Before marking Go work complete:
- Code formatted:
gofmt -w . - Tests pass:
go test ./... - Static analysis clean:
go vet ./... - Linting clean:
golangci-lint run - All errors handled (no
_for errors) - Dependencies tidy:
go mod tidy - Context propagated where needed
- Exported functions have comments
Quick Reference
| Task | Command |
|---|---|
| Init module | go mod init module-name |
| Add dependency | go get github.com/pkg/name |
| Run tests | go test ./... |
| Run with coverage | go test -cover ./... |
| Format code | gofmt -w . |
| Static analysis | go vet ./... |
| Lint | golangci-lint run |
| Tidy dependencies | go mod tidy |
| Build | go build ./... |
| Run | go run ./cmd/app |