Project Patterns
References: Examples
Functional Options
Example
Use With* functions for configurable constructors:
func NewClient(baseURL string, options ...ClientOption) *Client {
opts := defaultOptions()
for _, option := range options {
option(opts)
}
// create client...
}
client := NewClient(url, WithTimeout(30*time.Second), WithRetryCount(3))
Must Pattern
Example
Allowed only in cmd/, internal/apps/ - to fail fast on misconfiguration.
func Must[T any](f func() (T, error)) T {
v, err := f()
if err != nil { panic(err) }
return v
}
Caching Decorator
Example
Wrap clients with cache layer for transparent caching.
Error Handling
Example
| Rule |
Example |
| Wrap with context |
fmt.Errorf("get order %s: %w", id, err) |
| Check with Is/As |
errors.Is(err, ErrNotFound) |
| Handle once |
Don't log AND return |
| Custom errors |
var ErrFoo = errors.New() or type FooError struct{} |
Configuration
Example
| Type |
Path |
| App config |
config/appconfig/{env}.json |
| Infra config |
config/appconfig/infra-{env}.json |
| SSM |
/myservice/{env}/app/config |
Rules: No ARNs in app config, no secrets in files, use time.Duration with custom unmarshaler
HTTP Client with Retry
Example
client := tracing.NewRestyClient(baseURL,
tracing.WithTimeout(30*time.Second),
tracing.WithRetryCount(3),
tracing.WithExponentialBackoff(true),
)
DynamoDB Key Design
Example
Use composite keys (PK + SK), GSIs for query patterns.
Feature Flags
Example
Fallback defaults, check at service layer, log evaluations.
JSON Tags
Example
Use camelCase for JSON tags and query params.
Request Validation
Example
Use ozzo-validation for struct validation.
Libraries
| Library |
Purpose |
chi |
HTTP router |
samber/lo |
Collections/utilities |
ozzo-validation |
Validation |
resty |
HTTP client |