SoFunction
Updated on 2025-03-04

Example description of go defer and closures (not internal implementation)

golang's closure function

Use a few examples to illustrate golang's closure function, combined with defer, and combined with the corresponding code and summary at the end of the article.

function illustrate Output
e1 The defer call is equivalent to getting a snapshot of the current err variable, that is, when registering the defer function, the current err value is stuffed into the defer start err1
e2 defer is called, but a closure function and the closure function has a parameter. The closure captures the current value of the err is still start err2 (the closure captures a copy of the variable value), and the change of the value variable in the closure will not affect the value of the external err (see e5 for details) start err2
e3 defer call, variables in closures and variables outside anonymous functions are common, no formal parameters are passed, no formal parameters are passed, and they are shared with the context defer3 error
e4 The defer call, in function e4, when you pass err as an argument to the closure function, you actually create a copy of the closure function, which is independent of the external scope inside the closure. This behavior is because when the closure captures external variables, it will copy the current value of the external variable to the inside of the closure to form a closure environment. Now I understand the concept of closure. Specifically, when the defer statement is executed, the closure function will copy the current value of err (i.e. "start err4") into the parameters inside the closure. After that, regardless of whether the err in the external scope changes, the parameter value inside the closure remains unchanged because the closure has captured a snapshot. start err4
e5 When passing values, the change of the value variable in the closure will not affect the external err value (independent of each other) now err is start err5 start err5CHANGE ME
e6 The closure has no value passed, the err obtained is the last value assigned. now err is start err6 defer6 error CHANGE ME
package main
import (
    "errors"
    "fmt"
)
func e1(){
    err := ("start err1")
    defer (err)
    err = ("defer1 error")
    return
}
func e2(){
    err := ("start err2")
    defer func(e error) {
        (e)
    }(err)
    err = ("defer2 error")
    return
}
func e3(){
    err := ("start err3")
    //Variables in closures and variables outside anonymous functions are common, no formal parameters are passed, no formal parameters are passed, and they are shared with the context    defer func() {
        (err)
    }()
    err = ("defer3 error")
    return
}
func e4(){
    var err error
    err = ("start err4")
    //Variables in closures and variables outside anonymous functions are common, but if formal parameters are passed, it will be shared with the above    //In function e4, when you pass err as an argument to the closure function, you actually create a copy of the closure function, which is independent of the external scope inside the closure.  This behavior is because when the closure captures the external variable, it will copy the current value of the external variable to the inside of the closure, forming a closure environment    //Specifically, when the defer statement is executed, the closure function will copy the current value of err (i.e. "start err4") into the parameters inside the closure.  After that, the parameter values ​​inside the closure remain unchanged regardless of whether the err in the external scope change, because the closure has captured a snapshot.    defer func(err error) {
        (err)
    }(err)
    err = ("defer4 error")
    return
}
func e5(){
    err := ("start err4")
    defer func(err error ) {
        err=(()+"CHANGE ME")
        (err)
    }(err)
    ("now err is ",err)
    err = ("defer5 error")
    return
}
func e6() {
    err := ("start err6")
    defer func() {
        err = (() + " CHANGE ME")
        (err)
    }()
    ("now err is ", err)
    err = ("defer6 error")
    return
}
func main(){
    e1()
    e2()
    e3()
    e4()
    e5()
    e6()
}

Variable scope and closures

The scope of variables in Go is determined by the code block. Variables are visible within the code blocks they define.

A closure is a function value that captures variables within the scope around it when it is defined.

The closure can be called outside the definition, still accessing and modifying the captured variables.

Closure and variable capture

Closure functions can capture variables in external scopes. Inside the closure, they can access the values ​​of external variables.

The variable captured by the closure is a copy of its, that is, the closure uses a copy of the variable value inside it.

Modifying variables captured inside a closure will not affect variables in the external scope unless you directly modify variables in the external scope within the closure.

Closure parameter passing

Receiving variables with external scope as parameters inside the closure can cause the closure to operate on variables with external scope.

Using closure parameter passes can effectively isolate variables inside and outside the closure, thus maintaining predictability.

Closure in defer

When using closures in a defer statement, variables inside the closure are "captured" and used when defer is executed.
Modifying variables captured by closures inside closures will not affect variables in the external scope unless you directly modify variables in the external scope.

Summarize

Closures are a powerful concept that allows functions to have state and delay execution.

Understanding how closures operate on variable scopes and how they capture and modify variables is the key to writing efficient, clear Go code.

When operating variables in closures, pay attention to the variable scope, captured variable copy, and its impact on external scope.

The above is the detailed content of go defer and closure examples (not internal implementation). For more information about go defer closures, please follow my other related articles!