Pattern
ctx, span := tracing.StartSpan(ctx, "operation")
var err error
defer func() { span.End(err) }() // captures final value of err
err = doSomething()
if err != nil {
return nil, err // deferred func runs with this err
}
return result, nil // deferred func runs with nilThe closure captures err by reference — it reads the variable’s final value at exit time, not its value when defer was registered. This means you don’t need to call span.End(err) before every return.
Cleanup stack (LIFO)
defer conn.Close() // runs third
defer cancel() // runs second
defer span.End(err) // runs firstDeferred functions execute in reverse order — last registered, first run.
See also
- context-independent-cleanup — use context.Background() in deferred cleanup, not the request context