andrewhowdencom-go
SKILL.md
Go
Follow Effective Go as the baseline.
Project Structure
We follow the standard layout. See Layout Reference for details.
- cmd/: Main applications.
- internal/: Private application logic.
Inlined Expertise: Common Patterns
1. Functional Options Pattern
Use for object construction with optional parameters.
type Server struct {
timeout time.Duration
}
type Option func(*Server)
func WithTimeout(t time.Duration) Option {
return func(s *Server) { s.timeout = t }
}
func New(opts ...Option) *Server {
s := &Server{timeout: 30 * time.Second} // Default
for _, opt := range opts {
opt(s)
}
return s
}
2. Table-Driven Tests
The standard for unit testing.
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
want int
}{
{"positive", 1, 2, 3},
{"negative", -1, -1, -2},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Add(tt.a, tt.b); got != tt.want {
t.Errorf("Add() = %v, want %v", got, tt.want)
}
})
}
}
3. Error Handling
Wrap upstream errors to provide context.
if err := dest.Do(); err != nil {
return fmt.Errorf("failed to do action: %w", err)
}
4. Logging
Use log/slog with TextHandler.
- Debug: Detailed info for development.
- Lifecycle: Startup/shutdown events.
- Forbidden: Do NOT use logs for access tracking (use Tracing).
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
slog.Info("starting application", "version", version)
Tooling
- Linting: use
golangci-lint. - Testing: always use
go test -race ./.... - See Tooling Reference for deeper configuration.