Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Go-specific design patterns and best practices including functional options, small interfaces, dependency injection, concurrency patterns, error handling, and package organization. Use when working with Go code to apply idiomatic Go patterns.
.claude/skills/kunanonj-golang-patterns/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 132% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 9% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 24% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 28% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 7% | 0% |
> This skill provides comprehensive Go patterns extending common design principles with Go-specific idioms.
Use the functional options pattern for flexible constructor configuration:
gotype Option func(*Server) func WithPort(port int) Option { return func(s *Server) { s.port = port } } func NewServer(opts ...Option) *Server { s := &Server{port: 8080} for _, opt := range opts { opt(s) } return s }
Benefits:
Define interfaces where they are used, not where they are implemented.
Principle: Accept interfaces, return structs
go// Good: Small, focused interface defined at point of use type UserStore interface { GetUser(id string) (*User, error) } func ProcessUser(store UserStore, id string) error { user, err := store.GetUser(id) // ... }
Benefits:
Use constructor functions to inject dependencies:
gofunc NewUserService(repo UserRepository, logger Logger) *UserService { return &UserService{ repo: repo, logger: logger, } }
Pattern:
gofunc workerPool(jobs <-chan Job, results chan<- Result, workers int) { var wg sync.WaitGroup for i := 0; i < workers; i++ { wg.Add(1) go func() { defer wg.Done() for job := range jobs { results <- processJob(job) } }() } wg.Wait() close(results) }
Always pass context as first parameter:
gofunc FetchUser(ctx context.Context, id string) (*User, error) { // Check context cancellation select { case <-ctx.Done(): return nil, ctx.Err() default: } // ... fetch logic }
goif err != nil { return fmt.Errorf("failed to fetch user %s: %w", id, err) }
gotype ValidationError struct { Field string Msg string } func (e *ValidationError) Error() string { return fmt.Sprintf("%s: %s", e.Field, e.Msg) }
govar ( ErrNotFound = errors.New("not found") ErrInvalid = errors.New("invalid input") ) // Check with errors.Is if errors.Is(err, ErrNotFound) { // handle not found }
project/
├── cmd/ # Main applications
│ └── server/
│ └── main.go
├── internal/ # Private application code
│ ├── domain/ # Business logic
│ ├── handler/ # HTTP handlers
│ └── repository/ # Data access
└── pkg/ # Public librariesuser.User not user.UserModelinternal/ for private codemain package minimalgofunc TestValidate(t *testing.T) { tests := []struct { name string input string wantErr bool }{ {"valid", "test@example.com", false}, {"invalid", "not-an-email", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := Validate(tt.input) if (err != nil) != tt.wantErr { t.Errorf("got error %v, wantErr %v", err, tt.wantErr) } }) } }
gofunc testDB(t *testing.T) *sql.DB { t.Helper() db, err := sql.Open("sqlite3", ":memory:") if err != nil { t.Fatalf("failed to open test db: %v", err) } t.Cleanup(func() { db.Close() }) return db }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 14,598 | 8,952 | -39% | 1 | 1 | 0% | 2,657 | 2,886 | +9% | 0 | 0 | — |
case-02 | pass→pass | 10,876 | 7,289 | -33% | 1 | 1 | 0% | 1,981 | 2,461 | +24% | 0 | 0 | — |
case-03 | pass→pass | 11,487 | 8,364 | -27% | 1 | 1 | 0% | 2,020 | 2,582 | +28% | 0 | 0 | — |
case-04 | pass→pass | 15,167 | 7,406 | -51% | 1 | 1 | 0% | 2,481 | 2,651 | +7% | 0 | 0 | — |
case-05 | fail→pass | 4,599 | 4,661 | +1% | 1 | 1 | 0% | 849 | 1,972 | +132% | 0 | 0 | — |
case-06 | pass→pass | 4,751 | 4,025 | -15% | 1 | 1 | 0% | 947 | 1,972 | +108% | 0 | 0 | — |
case-07 | pass→pass | 7,978 | 5,034 | -37% | 1 | 1 | 0% | 1,568 | 2,080 | +33% | 0 | 0 | — |
case-08 | pass→pass | 8,200 | 3,746 | -54% | 1 | 1 | 0% | 1,636 | 1,828 | +12% | 0 | 0 | — |
case-09 | pass→pass | 7,596 | 3,595 | -53% | 1 | 1 | 0% | 1,322 | 1,764 | +33% | 0 | 0 | — |
case-10 | pass→pass | 11,421 | 5,327 | -53% | 1 | 1 | 0% | 1,897 | 2,082 | +10% | 0 | 0 | — |
case-11 | pass→pass | 9,924 | 7,199 | -27% | 1 | 1 | 0% | 2,020 | 2,515 | +25% | 0 | 0 | — |
case-12 | pass→pass | 6,309 | 4,809 | -24% | 1 | 1 | 0% | 1,329 | 2,014 | +52% | 0 | 0 | — |
case-13 | pass→pass | 2,418 | 3,081 | +27% | 1 | 1 | 0% | 442 | 1,728 | +291% | 0 | 0 | — |
case-14 | pass→pass | 7,353 | 3,034 | -59% | 1 | 1 | 0% | 1,297 | 1,646 | +27% | 0 | 0 | — |
case-15 | pass→pass | 8,304 | 4,147 | -50% | 1 | 1 | 0% | 1,546 | 1,777 | +15% | 0 | 0 | — |
case-16 | pass→pass | 5,923 | 2,668 | -55% | 1 | 1 | 0% | 1,047 | 1,605 | +53% | 0 | 0 | — |
case-17 | pass→pass | 9,559 | 7,784 | -19% | 1 | 1 | 0% | 1,935 | 2,581 | +33% | 0 | 0 | — |
case-18 | pass→pass | 13,360 | 12,206 | -9% | 1 | 1 | 0% | 2,296 | 3,349 | +46% | 0 | 0 | — |
case-19 | pass→pass | 14,067 | 11,067 | -21% | 1 | 1 | 0% | 2,571 | 3,155 | +23% | 0 | 0 | — |
case-20 | pass→pass | 14,734 | 10,057 | -32% | 1 | 1 | 0% | 2,784 | 3,087 | +11% | 0 | 0 | — |
case-21 | pass→pass | 8,023 | 4,977 | -38% | 1 | 1 | 0% | 1,735 | 2,114 | +22% | 0 | 0 | — |
case-22 | pass→pass | 7,453 | 7,005 | -6% | 1 | 1 | 0% | 1,572 | 2,503 | +59% | 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. 22 cases were attempted. The headline lift of +5 percentage points is the difference between those two pass rates over the 22 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.