Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when reading or writing Go files (.go, go.mod).
.claude/skills/aiskillstore-go-best-practices/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | -9% | 0% |
| case-04 | ✗→✓ | ▲ Improved | -8% | 0% |
| case-08 | ✓→✓ | = Same ✓ | 4% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 18% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 5% | 0% |
Follows type-first, functional, and error handling patterns from CLAUDE.md. This skill covers language-specific idioms only.
Use Go's type system to prevent invalid states at compile time.
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 } // 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 UserRepository interface { GetByID(ctx context.Context, id UserID) (*User, error) Save(ctx context.Context, user *User) error } // Accept interfaces, return structs func ProcessInput(r io.Reader) ([]byte, error) { return io.ReadAll(r) }
Enums with iota and exhaustive switch:
gotype Status int const ( StatusActive Status = iota + 1 StatusInactive StatusPending ) 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:
gotype ServerOption func(*Server) func WithPort(port int) ServerOption { return func(s *Server) { s.port = port } } func NewServer(opts ...ServerOption) *Server { s := &Server{port: 8080, timeout: 30 * time.Second} for _, opt := range opts { opt(s) } return s } // Usage: NewServer(WithPort(3000), WithTimeout(time.Minute))
Embed for composition:
gotype Timestamps struct { CreatedAt time.Time UpdatedAt time.Time } type User struct { Timestamps // User gains CreatedAt, UpdatedAt ID UserID Email string }
Wrap errors with %w to preserve the chain for errors.Is / errors.As:
goout, err := client.Do(ctx, req) if err != nil { return nil, fmt.Errorf("fetch widget failed: %w", err) }
Use log/slog with structured key-value pairs:
goimport "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 }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-08 | pass→pass | 11,094 | 7,529 | -32% | 1 | 1 | 0% | 2,035 | 2,121 | +4% | 0 | 0 | — |
case-02 | fail→pass | 16,643 | 9,781 | -41% | 1 | 1 | 0% | 3,034 | 2,762 | -9% | 0 | 0 | — |
case-03 | pass→pass | 10,975 | 8,358 | -24% | 1 | 1 | 0% | 1,886 | 2,217 | +18% | 0 | 0 | — |
case-01 | pass→pass | 16,057 | 12,124 | -24% | 1 | 1 | 0% | 2,944 | 3,096 | +5% | 0 | 0 | — |
case-04 | fail→pass | 17,185 | 13,616 | -21% | 1 | 1 | 0% | 3,321 | 3,056 | -8% | 0 | 0 | — |
case-05 | pass→pass | 10,597 | 8,216 | -22% | 1 | 1 | 0% | 2,075 | 2,354 | +13% | 0 | 0 | — |
case-06 | pass→pass | 2,754 | 3,112 | +13% | 1 | 1 | 0% | 471 | 1,285 | +173% | 0 | 0 | — |
case-07 | pass→pass | 17,338 | 10,462 | -40% | 1 | 1 | 0% | 3,330 | 2,845 | -15% | 0 | 0 | — |
case-09 | fail→fail | 8,336 | 6,876 | -18% | 1 | 1 | 0% | 1,522 | 1,884 | +24% | 0 | 0 | — |
case-10 | pass→pass | 13,116 | 9,249 | -29% | 1 | 1 | 0% | 2,107 | 2,077 | -1% | 0 | 0 | — |
case-11 | pass→pass | 10,383 | 7,486 | -28% | 1 | 1 | 0% | 1,916 | 2,087 | +9% | 0 | 0 | — |
case-12 | pass→pass | 9,072 | 5,157 | -43% | 1 | 1 | 0% | 1,838 | 1,543 | -16% | 0 | 0 | — |
case-13 | pass→pass | 9,379 | 6,635 | -29% | 1 | 1 | 0% | 1,815 | 1,977 | +9% | 0 | 0 | — |
case-14 | pass→pass | 7,748 | 3,986 | -49% | 1 | 1 | 0% | 1,335 | 1,343 | +1% | 0 | 0 | — |
case-15 | pass→pass | 5,643 | 4,846 | -14% | 1 | 1 | 0% | 1,053 | 1,652 | +57% | 0 | 0 | — |
case-16 | pass→pass | 6,284 | 5,754 | -8% | 1 | 1 | 0% | 1,221 | 1,420 | +16% | 0 | 0 | — |
case-17 | pass→pass | 7,867 | 3,673 | -53% | 1 | 1 | 0% | 1,373 | 1,315 | -4% | 0 | 0 | — |
case-18 | pass→pass | 4,167 | 2,679 | -36% | 1 | 1 | 0% | 744 | 1,193 | +60% | 0 | 0 | — |
case-19 | fail→fail | 6,946 | 5,615 | -19% | 1 | 1 | 0% | 1,251 | 1,694 | +35% | 0 | 0 | — |
case-20 | pass→pass | 15,018 | 11,617 | -23% | 1 | 1 | 0% | 2,827 | 3,044 | +8% | 0 | 0 | — |
case-21 | pass→pass | 12,542 | 10,354 | -17% | 1 | 1 | 0% | 2,662 | 2,920 | +10% | 0 | 0 | — |
case-22 | pass→pass | 9,249 | 7,225 | -22% | 1 | 1 | 0% | 1,738 | 2,189 | +26% | 0 | 0 | — |
case-23 | pass→pass | 11,450 | 11,321 | -1% | 1 | 1 | 0% | 2,421 | 2,937 | +21% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +9 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.