Go Uber Style Guide
Overview
This skill provides comprehensive guidance for writing idiomatic Go code that strictly follows the Uber Go Style Guide. It emphasizes Test-Driven Development (TDD), proper error handling without exceptions, safe concurrency patterns, and Go's unique language idioms including zero values, composition over inheritance, and interface design.
When to Use This Skill
Use this skill for any Go-related programming task:
- Writing new Go code or implementing new features
- Reviewing existing Go code for best practices and idioms
- Refactoring code to follow Uber Go Style Guide
- Debugging Go applications and fixing issues
- Optimizing Go code for performance
- Implementing concurrent/parallel operations safely
- Designing Go APIs and package structures
Core Go Philosophy
Mandatory Principles
1. Test-Driven Development (TDD)
- Always write tests first using the Red-Green-Refactor cycle
- Use table-driven tests for comprehensive coverage
- Tests must be in place before implementation code
2. Explicit Error Handling
- Go does not use exceptions - use error values exclusively
- Always handle errors explicitly, never ignore them
- Wrap errors with context using
fmt.Errorf with %w
- Use sentinel errors for matching specific error conditions
3. Single Exit Point Pattern
- Use the
run() pattern to centralize exit logic in main()
- This keeps
main() functions clean and testable
4. Go Idioms
- Leverage zero values (e.g.,
var mu sync.Mutex is ready to use)
- Accept interfaces, return concrete types
- Use composition over inheritance
- Prefer nil slices over empty slices for "not found" cases
Workflow
For Writing New Go Code
Write the test first (TDD mandatory)
- Define the function signature and expected behavior in a test
- Run test to see it fail (Red)
Implement minimal code to pass the test (Green)
- Write just enough code to make the test pass
- Follow Uber Go Style Guide conventions
Refactor while keeping tests green
- Improve code quality, readability, and performance
- Ensure all tests still pass
Verify quality standards
- Run
go fmt to format code
- Run
go vet to catch common mistakes
- Run
go test -race to detect race conditions
- Check function size (≤50 lines) and parameter count (≤4)
For Code Review
Check TDD compliance
- Verify tests exist and are comprehensive
- Ensure table-driven test pattern is used where appropriate
Review Uber Go Style Guide compliance
- Check file organization (imports, types, constructors, methods, functions)
- Verify structural limits (function ≤50 lines, struct ≤200 lines, ≤4 parameters)
- Confirm proper error handling patterns
Validate interface design
- Ensure interfaces are small and focused
- Check that compile-time interface verification is present
- Verify "accept interfaces, return concrete types" pattern
Check for Go-specific issues
- Look for improper error handling (ignored errors, panics in library code)
- Verify concurrency safety (proper mutex usage, context handling)
- Check for proper resource cleanup (defer patterns)
For Refactoring
Ensure tests exist first
- If no tests, write them before refactoring
- Tests provide safety net during refactoring
Identify anti-patterns
- Functions >50 lines
4 parameters (use functional options pattern instead)
- Ignored errors
- Missing defer for cleanup
- Improper interface design
Refactor incrementally
- Make one change at a time
- Keep tests passing after each change
- Commit working code frequently
Structural Limits (Uber Go Style Guide)
- Functions: ≤50 lines maximum (Go-specific override from general 20-line guideline)
- Structs: ≤200 lines maximum
- Parameters: ≤4 parameters per function (use functional options pattern for more)
- Exception Rule: Break limits only with clear documentation and explicit approval
Reference Materials
For detailed code patterns, examples, and guidelines, consult the reference files:
references/uber-go-patterns.md - Comprehensive Uber Go Style Guide patterns and anti-patterns
- Pointers to interfaces, receivers, embedding, mutable globals, init(), field tags
- Time handling, enums, atomic operations
- File organization and naming conventions
references/error-handling.md - Error wrapping, sentinel errors, and error matching patterns
references/concurrency-safety.md - Safe concurrent programming patterns in Go
- CRITICAL: Channel sizing (unbuffered or size 1 only)
- CRITICAL: No fire-and-forget goroutines
- CRITICAL: No goroutines in init()
references/performance.md - Performance optimization patterns
- Prefer strconv over fmt for primitives
- Avoid repeated string-to-byte conversions
- Container pre-allocation strategies
references/testing-patterns.md - Table-driven testing examples and TDD workflows
Use grep to search these files for specific patterns when needed:
grep -r "functional options" references/
grep -r "channel size" references/concurrency-safety.md
grep -r "strconv" references/performance.md
Template Assets
Pre-built templates are available in assets/templates/ for common Go patterns:
assets/templates/main_single_exit.go - Single exit point pattern for main()
assets/templates/table_test.go - Table-driven test template
assets/templates/functional_options.go - Functional options pattern for >4 parameters
assets/templates/http_handler.go - HTTP handler with proper error handling
Copy and customize these templates as starting points for new code.
Quality Assurance Checklist
Before delivering Go code, verify:
Critical Uber Go Rules:
Code Quality:
Error Handling:
Interfaces:
Performance (when relevant):
Time & Enums:
Communication Guidelines
When providing Go coding assistance:
- Reference Uber Go Style Guide for rationale
- Provide working, tested code examples
- Explain trade-offs in Go context
- Suggest Go tools (
go vet, golangci-lint, staticcheck)
- Point out Go-specific pitfalls and solutions
- Prioritize Go's philosophy of simplicity and explicitness
Key Differences from General Coding Principles
This skill overrides some general coding principles with Go-specific rules:
- Function length: 50 lines (vs. general 20 lines) - Go's explicit error handling naturally leads to longer functions
- Error handling: No exceptions, only error values - completely different from exception-based languages
- Testing approach: TDD is mandatory, not optional - critical to Go development workflow
- Parameter limits: Strict ≤4 parameter limit with functional options pattern as solution
1---2name: go-uber-style3description: Use this skill when writing Go code following the Uber Go Style Guide. Provides comprehensive guidance on idiomatic Go patterns, error handling, concurrency safety, performance optimization, and test-driven development. Covers all critical Uber Go rules including channel sizing, goroutine management, interface design, and proper error handling. Appropriate for any task involving .go files, Go code reviews, refactoring, or implementing Go best practices.4---5
6# Go Uber Style Guide
7
8## Overview
9
10This skill provides comprehensive guidance for writing idiomatic Go code that strictly follows the Uber Go Style Guide. It emphasizes Test-Driven Development (TDD), proper error handling without exceptions, safe concurrency patterns, and Go's unique language idioms including zero values, composition over inheritance, and interface design.
11
12## When to Use This Skill
13
14Use this skill for any Go-related programming task:
15- Writing new Go code or implementing new features
16- Reviewing existing Go code for best practices and idioms
17- Refactoring code to follow Uber Go Style Guide
18- Debugging Go applications and fixing issues
19- Optimizing Go code for performance
20- Implementing concurrent/parallel operations safely
21- Designing Go APIs and package structures
22
23## Core Go Philosophy
24
25### Mandatory Principles
26
27**1. Test-Driven Development (TDD)**
28- Always write tests first using the Red-Green-Refactor cycle
29- Use table-driven tests for comprehensive coverage
30- Tests must be in place before implementation code
31
32**2. Explicit Error Handling**
33- Go does not use exceptions - use error values exclusively
34- Always handle errors explicitly, never ignore them
35- Wrap errors with context using `fmt.Errorf` with `%w`
36- Use sentinel errors for matching specific error conditions
37
38**3. Single Exit Point Pattern**
39- Use the `run()` pattern to centralize exit logic in `main()`
40- This keeps `main()` functions clean and testable
41
42**4. Go Idioms**
43- Leverage zero values (e.g., `var mu sync.Mutex` is ready to use)
44- Accept interfaces, return concrete types
45- Use composition over inheritance
46- Prefer nil slices over empty slices for "not found" cases
47
48## Workflow
49
50### For Writing New Go Code
51
521. **Write the test first** (TDD mandatory)
53 - Define the function signature and expected behavior in a test
54 - Run test to see it fail (Red)
55
562. **Implement minimal code to pass the test** (Green)
57 - Write just enough code to make the test pass
58 - Follow Uber Go Style Guide conventions
59
603. **Refactor while keeping tests green**
61 - Improve code quality, readability, and performance
62 - Ensure all tests still pass
63
644. **Verify quality standards**
65 - Run `go fmt` to format code
66 - Run `go vet` to catch common mistakes
67 - Run `go test -race` to detect race conditions
68 - Check function size (≤50 lines) and parameter count (≤4)
69
70### For Code Review
71
721. **Check TDD compliance**
73 - Verify tests exist and are comprehensive
74 - Ensure table-driven test pattern is used where appropriate
75
762. **Review Uber Go Style Guide compliance**
77 - Check file organization (imports, types, constructors, methods, functions)
78 - Verify structural limits (function ≤50 lines, struct ≤200 lines, ≤4 parameters)
79 - Confirm proper error handling patterns
80
813. **Validate interface design**
82 - Ensure interfaces are small and focused
83 - Check that compile-time interface verification is present
84 - Verify "accept interfaces, return concrete types" pattern
85
864. **Check for Go-specific issues**
87 - Look for improper error handling (ignored errors, panics in library code)
88 - Verify concurrency safety (proper mutex usage, context handling)
89 - Check for proper resource cleanup (defer patterns)
90
91### For Refactoring
92
931. **Ensure tests exist first**
94 - If no tests, write them before refactoring
95 - Tests provide safety net during refactoring
96
972. **Identify anti-patterns**
98 - Functions >50 lines
99 - >4 parameters (use functional options pattern instead)
100 - Ignored errors
101 - Missing defer for cleanup
102 - Improper interface design
103
1043. **Refactor incrementally**
105 - Make one change at a time
106 - Keep tests passing after each change
107 - Commit working code frequently
108
109## Structural Limits (Uber Go Style Guide)
110
111- **Functions**: ≤50 lines maximum (Go-specific override from general 20-line guideline)
112- **Structs**: ≤200 lines maximum
113- **Parameters**: ≤4 parameters per function (use functional options pattern for more)
114- **Exception Rule**: Break limits only with clear documentation and explicit approval
115
116## Reference Materials
117
118For detailed code patterns, examples, and guidelines, consult the reference files:
119
120- `references/uber-go-patterns.md` - Comprehensive Uber Go Style Guide patterns and anti-patterns
121 - Pointers to interfaces, receivers, embedding, mutable globals, init(), field tags
122 - Time handling, enums, atomic operations
123 - File organization and naming conventions
124- `references/error-handling.md` - Error wrapping, sentinel errors, and error matching patterns
125- `references/concurrency-safety.md` - Safe concurrent programming patterns in Go
126 - **CRITICAL**: Channel sizing (unbuffered or size 1 only)
127 - **CRITICAL**: No fire-and-forget goroutines
128 - **CRITICAL**: No goroutines in init()
129- `references/performance.md` - Performance optimization patterns
130 - Prefer strconv over fmt for primitives
131 - Avoid repeated string-to-byte conversions
132 - Container pre-allocation strategies
133- `references/testing-patterns.md` - Table-driven testing examples and TDD workflows
134
135Use grep to search these files for specific patterns when needed:
136```bash
137grep -r "functional options" references/
138grep -r "channel size" references/concurrency-safety.md
139grep -r "strconv" references/performance.md
140```
141
142## Template Assets
143
144Pre-built templates are available in `assets/templates/` for common Go patterns:
145
146- `assets/templates/main_single_exit.go` - Single exit point pattern for main()
147- `assets/templates/table_test.go` - Table-driven test template
148- `assets/templates/functional_options.go` - Functional options pattern for >4 parameters
149- `assets/templates/http_handler.go` - HTTP handler with proper error handling
150
151Copy and customize these templates as starting points for new code.
152
153## Quality Assurance Checklist
154
155Before delivering Go code, verify:
156
157**Critical Uber Go Rules:**
158- [ ] No pointers to interfaces (`*io.Reader` is wrong)
159- [ ] Channels are unbuffered or size 1 only
160- [ ] No fire-and-forget goroutines (all have stop mechanism)
161- [ ] No goroutines in `init()`
162- [ ] No embedding types in public structs (unless method promotion is explicit)
163- [ ] Field tags on all marshaled struct fields (`json:"field"`)
164- [ ] No mutable global variables
165- [ ] No shadowing of built-in names (error, string, etc.)
166- [ ] Avoid `init()` unless truly necessary
167
168**Code Quality:**
169- [ ] Tests written first (TDD followed)
170- [ ] Functions ≤50 lines, structs ≤200 lines
171- [ ] ≤4 parameters per function (use functional options for more)
172- [ ] Code compiles with `go build`
173- [ ] Tests pass with `go test -race`
174- [ ] Code formatted with `go fmt`
175- [ ] No issues from `go vet`
176- [ ] Linting clean (`golangci-lint run`)
177
178**Error Handling:**
179- [ ] All errors handled explicitly (no `_` discards)
180- [ ] Errors wrapped with context (`%w`)
181- [ ] Single exit point in main()
182
183**Interfaces:**
184- [ ] Interfaces are small and focused
185- [ ] Interface compliance verified at compile time (`var _ Interface = (*Type)(nil)`)
186- [ ] Accept interfaces, return concrete types
187- [ ] Consistent receiver types (all pointer or all value)
188
189**Performance (when relevant):**
190- [ ] Use `strconv` for primitive string conversions (not `fmt`)
191- [ ] Pre-allocate slices/maps when size is known
192- [ ] Avoid repeated string-to-byte conversions in loops
193
194**Time & Enums:**
195- [ ] Use `time.Time` for instants, `time.Duration` for periods
196- [ ] Enums start at 1 (unless zero is meaningful)
197
198## Communication Guidelines
199
200When providing Go coding assistance:
201- Reference Uber Go Style Guide for rationale
202- Provide working, tested code examples
203- Explain trade-offs in Go context
204- Suggest Go tools (`go vet`, `golangci-lint`, `staticcheck`)
205- Point out Go-specific pitfalls and solutions
206- Prioritize Go's philosophy of simplicity and explicitness
207
208## Key Differences from General Coding Principles
209
210This skill overrides some general coding principles with Go-specific rules:
211- **Function length**: 50 lines (vs. general 20 lines) - Go's explicit error handling naturally leads to longer functions
212- **Error handling**: No exceptions, only error values - completely different from exception-based languages
213- **Testing approach**: TDD is mandatory, not optional - critical to Go development workflow
214- **Parameter limits**: Strict ≤4 parameter limit with functional options pattern as solution