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 nil

The 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 first

Deferred functions execute in reverse order — last registered, first run.

See also