Agent skill
go-best-practices
Go development best practices, patterns, and conventions. Use when writing Go code, reviewing .go files, discussing goroutines, channels, error handling, or Go project structure. Triggers on mentions of Go, Golang, goroutines, channels, defer, interfaces, go mod.
Install this agent skill to your Project
npx add-skill https://github.com/eous/dotclaude/tree/main/skills/go-best-practices
SKILL.md
Go Best Practices
Project Structure
project/
├── cmd/
│ └── myapp/
│ └── main.go
├── internal/
│ ├── handler/
│ ├── service/
│ └── repository/
├── pkg/
│ └── shared/
├── go.mod
└── go.sum
Error Handling
Always Check Errors
// Bad
result, _ := doSomething()
// Good
result, err := doSomething()
if err != nil {
return fmt.Errorf("doSomething failed: %w", err)
}
Wrap Errors with Context
func fetchUser(id string) (*User, error) {
user, err := db.Query(id)
if err != nil {
return nil, fmt.Errorf("fetch user %s: %w", id, err)
}
return user, nil
}
Sentinel Errors
var (
ErrNotFound = errors.New("not found")
ErrUnauthorized = errors.New("unauthorized")
)
// Check with errors.Is
if errors.Is(err, ErrNotFound) {
return http.StatusNotFound
}
Custom Error Types
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("%s: %s", e.Field, e.Message)
}
// Check with errors.As
var validErr *ValidationError
if errors.As(err, &validErr) {
log.Printf("validation failed on %s", validErr.Field)
}
Concurrency
Goroutines with WaitGroups
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(item Item) {
defer wg.Done()
process(item)
}(item)
}
wg.Wait()
Channels
// Buffered channel for bounded work
jobs := make(chan Job, 100)
// Signal-only channel
done := make(chan struct{})
// Close to broadcast
close(done)
Context for Cancellation
func fetchData(ctx context.Context, url string) error {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
Worker Pools
func worker(id int, jobs <-chan Job, results chan<- Result) {
for job := range jobs {
results <- process(job)
}
}
func main() {
jobs := make(chan Job, 100)
results := make(chan Result, 100)
// Start workers
for w := 0; w < 3; w++ {
go worker(w, jobs, results)
}
// Send jobs
for _, job := range allJobs {
jobs <- job
}
close(jobs)
}
Interfaces
Small Interfaces
// Good - single method
type Reader interface {
Read(p []byte) (n int, err error)
}
// Accept interfaces, return structs
func Process(r Reader) (*Result, error) {
// ...
}
Interface Composition
type ReadWriter interface {
Reader
Writer
}
Testing
Table-Driven Tests
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 2, 3, 5},
{"negative", -1, -2, -3},
{"zero", 0, 0, 0},
}
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)
}
})
}
}
Test Helpers
func setupTestDB(t *testing.T) *DB {
t.Helper()
db, err := NewDB(":memory:")
if err != nil {
t.Fatalf("setup db: %v", err)
}
t.Cleanup(func() { db.Close() })
return db
}
Resource Management
Defer for Cleanup
func readFile(path string) ([]byte, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
return io.ReadAll(f)
}
Mutex Patterns
type SafeCounter struct {
mu sync.RWMutex
value int
}
func (c *SafeCounter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.value++
}
func (c *SafeCounter) Value() int {
c.mu.RLock()
defer c.mu.RUnlock()
return c.value
}
Naming Conventions
- Packages: short, lowercase, no underscores (
http,json) - Exported:
PascalCase(NewServer,UserID) - Unexported:
camelCase(userID,conn) - Acronyms: consistent case (
URL,userID) - Getters: no
Getprefix (user.Name()notuser.GetName())
Common Patterns
Functional Options
type Server struct {
port int
timeout time.Duration
}
type Option func(*Server)
func WithPort(p int) Option {
return func(s *Server) { s.port = p }
}
func NewServer(opts ...Option) *Server {
s := &Server{port: 8080, timeout: 30 * time.Second}
for _, opt := range opts {
opt(s)
}
return s
}
Constructor Pattern
func NewUser(name string) (*User, error) {
if name == "" {
return nil, errors.New("name required")
}
return &User{Name: name, CreatedAt: time.Now()}, nil
}
Anti-Patterns to Avoid
- Naked returns in long functions
- Ignoring errors with
_ - Passing large structs by value
- Using
init()for complex logic - Global mutable state
- Goroutine leaks (always ensure cleanup)
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
typescript-best-practices
TypeScript development best practices, patterns, and conventions. Use when writing TypeScript code, reviewing .ts/.tsx files, discussing type safety, generics, utility types, or TypeScript project configuration. Triggers on mentions of TypeScript, tsconfig, type inference, generics, discriminated unions, React TypeScript.
api-design
REST and GraphQL API design patterns, best practices, and conventions. Use when designing APIs, discussing HTTP methods, status codes, versioning, or API documentation. Triggers on mentions of REST, API, GraphQL, endpoint, HTTP methods, OpenAPI, swagger, API versioning.
testing-patterns
Software testing patterns, strategies, and best practices. Use when writing tests, discussing test architecture, mocking, fixtures, or test organization. Triggers on mentions of testing, unit tests, integration tests, pytest, jest, mocking, fixtures, TDD, test coverage.
security-checklist
Application security best practices and vulnerability prevention. Use when reviewing code for security issues, implementing authentication, or discussing OWASP vulnerabilities. Triggers on mentions of security, authentication, authorization, XSS, SQL injection, CSRF, OWASP, encryption, secrets.
python-best-practices
Python development best practices, patterns, and conventions. Use when writing Python code, reviewing .py files, discussing pytest, asyncio, type hints, pydantic, dataclasses, or Python project structure. Triggers on mentions of Python, pytest, mypy, ruff, black, FastAPI, Django, Flask.
memory-generator
Generate CLAUDE.md project memory files by exploring codebases. Use when user asks to "generate memory", "create CLAUDE.md", "document this project", "understand this codebase", or starts work on a new/unfamiliar repository. Triggers on new project onboarding and documentation requests.
Didn't find tool you were looking for?