Lambda Expressions — Capture of variables

In Go, there are no lambda expressions in the same way as in some other languages like Python or JavaScript. However, you can achieve similar functionality using anonymous functions, which can capture and use variables from their surrounding scope. This feature allows for a form of closure, where the anonymous function retains access to the variables that were in scope when the function was defined.

Example: Capturing Variables in Anonymous Functions

Here's a basic example demonstrating how an anonymous function captures variables from its surrounding scope:

package main

import "fmt"

func main() {
    // Variable defined in the surrounding scope
    message := "Hello, Go!"

    // Anonymous function capturing the 'message' variable
    greet := func() {
        fmt.Println(message)
    }

    // Calling the anonymous function
    greet() // Output: Hello, Go!

    // Modifying the captured variable
    message = "Hello, Gophers!"

    // Calling the anonymous function again
    greet() // Output: Hello, Gophers!
}

Explanation

  1. Variable Capture: The message variable is defined in the surrounding scope of the anonymous function greet.
  2. Anonymous Function Definition: The anonymous function captures the message variable when it is defined.
  3. Function Call: When greet is called, it prints the value of message.
  4. Variable Modification: The value of message is modified, and subsequent calls to greet reflect this change.

Practical Example: Using Captured Variables in a Closure

Anonymous functions are often used in Go for tasks like event handling, goroutines, and higher-order functions. Here's a more practical example using a closure in a loop:

package main

import (
    "fmt"
    "time"
)

func main() {
    // Create a slice of strings
    messages := []string{"Hello, Go!", "Hello, Gophers!", "Hello, World!"}

    // Iterate over the slice and create goroutines
    for _, message := range messages {
        // Capture the current value of 'message' in the loop
        func(msg string) {
            go func() {
                fmt.Println(msg)
            }()
        }(message)
    }

    // Wait for a moment to allow all goroutines to finish
    time.Sleep(1 * time.Second)
}

Explanation

  1. Slice of Strings: A slice of strings is defined.
  2. Loop with Closure: In the loop, an anonymous function is used to capture the current value of message and pass it to another anonymous function that is run as a goroutine.
  3. Goroutines: Each goroutine prints the captured value of message.
  4. Sleep: A short sleep is added to allow all goroutines to complete before the program exits.

Capturing Variables with Different Lifetimes

When capturing variables in anonymous functions, it is important to understand the lifetime of the variables being captured: