Named result parameters
Use named results when they genuinely clarify a small function or a defer-based cleanup path; otherwise keep returns explicit.
Canonical guidance
- default to explicit return values
- use named results for small functions or precise deferred cleanup
- avoid naked returns in longer functions
Use when
- deferred close/rollback needs to update
err - signatures become clearer with result names
- short helper functions
Avoid
- long functions with hidden result mutation
- relying on naked returns for brevity
- using named results as a style default
Preferred pattern
func run(name string) (err error) {
f, err := os.Open(name)
if err != nil {
return err
}
defer func() {
if cerr := f.Close(); err == nil {
err = cerr
}
}()
return useFile(f)
}
Anti-pattern
- large functions where deferred logic mutates named results far from the eventual return
Explanation: This anti-pattern is tempting because named results can remove repetition, but hidden mutation usually costs more readability than it saves.
Why
- explicit returns keep control flow easier to audit
Related pages
Sources
- Effective Go - Go Team
- Go Code Review Comments - Go Team
- The Go Programming Language Specification - Go Team
- Named result parameters (#43-44) - Teiva Harsanyi