If you have any questions or suggestions, please contact us in time. My official account is “Brain fried Fish”, GitHub address: github.com/eddycjy.
Hello, I’m fried fish.
A few days ago, I saw a friend in the reader exchange group asking for technical questions related to Go. The question was: “Everyone, WHEN I learned to defer, I was at a loss when I met the closure. Who knows better and can give me some advice?”
doubt
His question is the following question of the Go language defer. Let’s have a look:
func main() {
var whatever [6]struct{}
for i := range whatever {
defer func() {
fmt.Println(i)
}()
}
}
Copy the code
Please think about the answer to the output first.
According to his own understanding, this small partner thinks that xx should be output. But the final output results, may be a deviation from its thinking, temporarily unable to think.
To reassure
The output of this program is:
5, 5, 5, 5Copy the code
Why is it all 5, why is it not 0, 1, 2, 3, 4, 5?
The root cause is closures, for two reasons:
- in
for
After the loop ends, local variablesi
Is already 5, anddefer
The closure of is a direct reference to the variable I. - In combination with
defer
Keyword characteristics can be known in themain
Execute after the method body ends.
Combined with the above, the final output is an increment of 5.
Think further
Now that we know why, let’s do another transformation. Let’s look at another case where the code looks like this:
func main() {
var whatever [6]struct{}
for i := range whatever {
defer func(i int) {
fmt.Println(i)
}(i)
}
}
Copy the code
Unlike the first case, this time we pass in the variable I. So what is his output?
The output of this program is:
5, 4, 3, 2, 1, 0Copy the code
Why 5, 4, 3, 2, 1, 0? Why not 0, 1, 2, 3, 4, 5? (Was the fried fish struck wrong?)
There are two fundamental reasons:
- in
for
When looping, local variablesi
Already passed indefer func
, belongs to value passing. Its value indefer
This is done when the statement is declared. - In combination with
defer
Keyword characteristics are pressedAfter the advancedIn order of execution.
Combined with the above, the final output is 5, 4, 3, 2, 1, 0.
Next question
After a while, this friend had a new feeling. A new sample problem was thrown as follows:
func f1() (r int) { defer func() { r++ }() return 0 } func f2() (r int) { t := 5 defer func() { t = t + 5 }() return t } func f3() (r int) { defer func(r int) { r = r + 5 }(r) return 1 }Copy the code
Main function:
func main() {
println(f1())
println(f2())
println(f3())
}
Copy the code
Please think about the answer to the output first.
The output of this program is:
5 1Copy the code
Why one, five, one, instead of zero, ten, five, or whatever?
You are welcome to discuss and share your ideas in the comments section below.
My official account
Share Go language, micro service architecture and strange system design, welcome to pay attention to my public number and I exchange and communication.
The best relationship is mutual achievement. Your praise is the biggest motivation for the creation of fried fish. Thank you for your support.