{
  "slug": "Common-Bug--Closure-Captures-a-Variable-from-the-Outer-Scope-a5ab7bed750b",
  "title": "🐞 Common Bug: Closure Captures a Variable from the Outer Scope",
  "subtitle": "Avoid closure bugs in Go goroutines by passing loop or shared variables as function parameters to ensure safe, race-free execution.",
  "excerpt": "Avoid closure bugs in Go goroutines by passing loop or shared variables as function parameters to ensure safe, race-free execution.",
  "date": "2025-07-19",
  "tags": [
    "Go"
  ],
  "readingTime": "1 min",
  "url": "https://medium.com/@mobinshaterian/common-bug-closure-captures-a-variable-from-the-outer-scope-a5ab7bed750b",
  "hero": "https://cdn-images-1.medium.com/max/800/1*1FNg_LwjlgGwfqHexk1UDA.jpeg",
  "content": [
    {
      "type": "heading",
      "level": 2,
      "text": "🐞 Common Bug: Closure Captures a Variable from the Outer Scope"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "🔍 What’s a Closure?"
    },
    {
      "type": "paragraph",
      "html": "A <strong>closure</strong> is a function that <em>captures variables from the surrounding scope</em>. 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."
    },
    {
      "type": "quote",
      "html": "Using the goroutine function without sending a variable as a parameter could cause bugs in the application."
    },
    {
      "type": "code",
      "lang": "go",
      "code": "go func(ct context.Context) {    t.sample(ct, *book)}(ctx)"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*1FNg_LwjlgGwfqHexk1UDA.jpeg",
      "alt": "🐞 Common Bug: Closure Captures a Variable from the Outer Scope",
      "caption": "",
      "width": 2304,
      "height": 1792
    },
    {
      "type": "heading",
      "level": 2,
      "text": "❌ The Problem: Closure over Book"
    },
    {
      "type": "paragraph",
      "html": "To fix the “book” Variables in your goroutine, they must be correctly captured and not <strong>shadowed</strong> or <strong>unexpectedly shared</strong> due to closures."
    },
    {
      "type": "paragraph",
      "html": "Here’s the common issue:"
    },
    {
      "type": "list",
      "ordered": false,
      "items": [
        "The “book” is being accessed <strong>inside the goroutine</strong>, but it was likely declared <strong>outside</strong> and may change before the goroutine runs (due to how closures work in Go).",
        "This can cause a <strong>race condition</strong> or unexpected “book” values inside the goroutine."
      ]
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*P_VjStIMimSnra0nOgsO5g.jpeg",
      "alt": "🐞 Common Bug: Closure Captures a Variable from the Outer Scope",
      "caption": "",
      "width": 2304,
      "height": 1792
    },
    {
      "type": "heading",
      "level": 2,
      "text": "✅ Correct Approach: Capture the Variable Properly"
    },
    {
      "type": "paragraph",
      "html": "Instead of relying on the closure capturing the variable, you can <strong>pass it explicitly as a parameter</strong>:"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "go func(ct context.Context, book Book) {    t.sample(ct, book)}(ctx, *book)"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "✅ Explanation:"
    },
    {
      "type": "list",
      "ordered": false,
      "items": [
        "Ensures the current value “book” is preserved.",
        "Now the goroutine gets its <strong>copy</strong> of the <code>book</code> value at the time the goroutine is created.",
        "The goroutine function takes a “book” <strong>parameter</strong>, making it safe and deterministic.",
        "This eliminates the closure over the <code>book</code> variable from the outer scope.",
        "This pattern is <strong>safe, deterministic</strong>, and avoids the potential race conditions or incorrect values."
      ]
    }
  ]
}
