Go quirks: function closures capturing mutable references
7 hours ago
- #Go programming
- #Closures
- #Concurrency
- Function closures in Go capture variables by reference, allowing them to see future writes to mutable data, which can lead to bugs if not handled carefully.
- Closures capturing pointers or mutable structs can cause data races, especially in concurrent code, as they share state with the original variable.
- To avoid issues, prefer capturing immutable values (e.g., strings, ints) or create snapshots of mutable data by copying values into local variables before closure creation.
- Method values in Go capture their receiver by reference, meaning they read live state from the receiver each time they are called.
- Go 1.22 changed loop-variable capture behavior to provide each iteration with its own copy, but pointer captures and method values on long-lived receivers still capture by reference.
- Tools like `go test -race` and `go vet`'s loopclosure checker can help detect some race conditions and loop-variable issues, but they may not catch all pitfalls.
- When closures need live state, use synchronization mechanisms like mutexes or atomic operations to ensure safe access, and document shared fields clearly.