Go backend patterns from Uber style and standard layout
Scanned 9/9/2026
Install to Claude Code
npx -y skills add baekenough/oh-my-customcode --skill go-backend-best-practices --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Go Backend Best Practices?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/baekenough-go-backend-best-practices)More formats (shields.io, HTML) on the badges page.
---
name: go-backend-best-practices
description: Go backend patterns from Uber style and standard layout
scope: core
user-invocable: false
---
## Purpose
Apply Go backend patterns for building production-ready services.
## Rules
### 1. Project Structure (Standard Layout)
```yaml
layout: "cmd/{server/main.go} + internal/{handler/,service/,repository/,model/} + pkg/{shared/} + api/{openapi.yaml} + configs/ + scripts/"
directories:
cmd: Main applications (one per binary)
internal: Private application code
pkg: Library code safe for external use
api: API definitions (OpenAPI, protobuf)
configs: Configuration files
scripts: Build and CI scripts
```
Reference: guides/go-backend/project-layout.md
### 2. Error Handling (Uber Style)
```yaml
principles:
- Wrap errors with context using %w
- Handle errors once (don't log AND return)
- Use sentinel errors for specific conditions
- Name error variables with Err prefix
patterns:
sentinel: "var ErrNotFound = errors.New(\"not found\")"
wrapping: "fmt.Errorf(\"getUser %s: %w\", id, err)"
checking: "errors.Is(err, ErrNotFound)"
```
Reference: guides/go-backend/uber-style.md
### 3. Concurrency (Uber Style)
```yaml
channels:
size: "Use 0 (unbuffered) or 1 only"
larger: "Requires careful review"
goroutines:
never: fire-and-forget
always: wait for completion or manage lifecycle
patterns: "sync.WaitGroup + error channel for parallel work; context.Context for cancellation"
```
Reference: guides/go-backend/uber-style.md
### 4. HTTP Server
```yaml
structure:
handler: HTTP layer (request/response)
service: Business logic
repository: Data access
patterns:
dependency_injection: "Handler struct with service field, constructor NewXxxHandler()"
router: "chi.NewRouter() with middleware (Logger, Recoverer) and versioned routes"
error_mapping: "errors.Is() to map domain errors to HTTP status codes"
```
Reference: guides/go-backend/uber-style.md
### 5. Dependency Injection
```yaml
approach: constructor injection
avoid: global variables
pattern: "Struct with dependencies as fields, New* constructor functions, wire up in main()"
```
Reference: guides/go-backend/uber-style.md
### 6. Configuration
```yaml
approach:
- Use environment variables
- Validate at startup
- Group related settings
pattern: "Config struct with nested typed configs, env struct tags, Parse at startup"
```
Reference: guides/go-backend/uber-style.md
### 7. Testing
```yaml
patterns:
table_driven: for comprehensive coverage
interfaces: for mocking
parallel: for speed
tools: "gomock for mocks, cmp.Diff for assertions"
```
Reference: guides/go-backend/uber-style.md
### 8. Performance (Uber Style)
```yaml
guidelines:
- Use strconv over fmt for conversions
- Pre-allocate slices with known capacity
- Avoid repeated string-to-byte conversions
- Copy slices/maps at boundaries
```
Reference: guides/go-backend/uber-style.md
## Application
When writing Go backend code:
1. **Always** use standard project layout
2. **Always** wrap errors with context
3. **Never** fire-and-forget goroutines
4. **Use** constructor injection
5. **Use** table-driven tests
6. **Handle** errors once
7. **Copy** data at boundaries
8. **Validate** config at startup
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!