In my code I try to use numAddr
to record the change of num after the defer statement
func deferRun() {
num := 1
numAddr := &num
defer fmt.Printf("num is %d", *numAddr)
num = 2
return
}
func main() {
deferRun()
}
but I get num is 1
instead of 2, why does the defer function use the value instead of address of *numAddr
?
then I try another way
func deferRun() {
num := 1
numAddr := &num
defer func(intAddr *int){
fmt.Printf("num is %d", *numAddr)
}(numAddr)
num = 2
fmt.Println("num is", *numAddr)
return
}
func main() {
deferRun()
}
This time it works and I get num is 2
, so I think maybe defer fmt.Printf(something)
stored the string immediately when it was declared and the numAddr is not used when the defer function actually run?
Interesting question. To answer the question, you must know a rule, as in this Go tutorial https://go.dev/tour/flowcontrol/12
The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.
.
Example 1: Telling the defer function to print value located in a specified memory address.
func deferRun() {
num := 1
numAddr := &num //address of variable num in stack memory, 0xc000076f38 for example
defer func(intAddr *int){
fmt.Printf("num is %d", *numAddr)
}(numAddr) //Hey Go, when the surrounding function returns, print the value located in this address (numAddr=0xc000076f38)
num = 2 //Now the value located in address 0xc000076f38 is 2
return
}
Output will be 2.
Example 2: Telling the defer function to print a specified value.
func deferRun() {
num := 1
numAddr := &num //address of variable num in stack memory, 0xc000076f38 for example
defer fmt.Printf("num is %d", *numAddr) //Hey Go, when the surrounding function returns, print the this value *numAddr (*numAddr is 1 for now)
num = 2 //Now the value located in address 0xc000076f38 is 2 but you told the defer function to print 1 before
return
}
Output will be 1.