🐞 Common Bug: Closure Captures a Variable from the Outer Scope

🔍 What’s a Closure?

A closure is a function that captures variables from the surrounding scope. In Go, when you define an anonymous function (like in a goroutine) that uses a variable from outside, it’s not copying the variable — it’s referencing it directly.

Using the goroutine function without sending a variable as a parameter could cause bugs in the application.
go
go func(ct context.Context) {    t.sample(ct, *book)}(ctx)

❌ The Problem: Closure over Book

To fix the “book” Variables in your goroutine, they must be correctly captured and not shadowed or unexpectedly shared due to closures.

Here’s the common issue:

  • The “book” is being accessed inside the goroutine, but it was likely declared outside and may change before the goroutine runs (due to how closures work in Go).
  • This can cause a race condition or unexpected “book” values inside the goroutine.
🐞 Common Bug: Closure Captures a Variable from the Outer Scope

✅ Correct Approach: Capture the Variable Properly

Instead of relying on the closure capturing the variable, you can pass it explicitly as a parameter:

go
go func(ct context.Context, book Book) {    t.sample(ct, book)}(ctx, *book)

✅ Explanation:

  • Ensures the current value “book” is preserved.
  • Now the goroutine gets its copy of the book value at the time the goroutine is created.
  • The goroutine function takes a “book” parameter, making it safe and deterministic.
  • This eliminates the closure over the book variable from the outer scope.
  • This pattern is safe, deterministic, and avoids the potential race conditions or incorrect values.