1
If you have any questions or suggestions, please communicate and collide in time. is [Fried fish in the brain], GitHub address: 1609b67e4767e7 https://github.com/eddycjy .

Hello everyone, I am fried fish.

A few days ago, I saw a small partner in the reader exchange group, asking you about Go-related technical issues.
The question is: " everybody, when I was learning defer and encountered closures, I was very . Who knows better and can give pointers? 1609b67e476832"

doubt

His question is the following defer topic of the Go language, let's take a look:

func main() {
    var whatever [6]struct{}
    for i := range whatever {
        defer func() {
            fmt.Println(i)
        }()
    }
}

Please think for yourself what the output answer is.

According to his own understanding, this little partner thinks that xx should be output. But the final output may deviate from what it thinks, and it's impossible to figure it out for a while.

Confuse

The output of this program is:

5
5
5
5
5
5

Why is it all 5, why not the output result like 0, 1, 2, 3, 4, 5?

The root cause is closure , there are two reasons:

  • After the for loop ends, i is already 5, and defer directly refers to the variable i.
  • Combined with defer keyword, it can be known that it will be main method body ends.

Combined with the above, the final output result is 5 which has been self-incremented.

Think further

Now that we understand why, let's transform it again. Look at another situation, the code is as follows:

func main() {
    var whatever [6]struct{}
    for i := range whatever {
        defer func(i int) {
            fmt.Println(i)
        }(i)
    }
}

Unlike the first case, we passed the i So what is his output?

The output of this program is:

5
4
3
2
1
0

Why is it 5, 4, 3, 2, 1, 0, why not 0, 1, 2, 3, 4, 5? (Is it the wrong type of fried fish?)

The fundamental reason lies in two points:

  • In the for loop, the local variable i has been passed into defer func , which belongs to value transfer. Its value is determined when the statement defer
  • Combined defer characteristic keywords, is based last-out order to be executed.

Combining the above, the final output result is 5, 4, 3, 2, 1, 0.

Next question

After a while, this little partner had a new insight. A new example question is 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
}

Main function:

func main() {
    println(f1())
    println(f2())
    println(f3())
}

Please think for yourself what the output answer is.

The output of this program is:

1
5
1

Why is it 1, 5, 1 instead of 0, 10, 5, or other answers?

Welcome everyone to discuss and share ideas for solving problems , think and make progress together.

My official account

Share Go language, microservice architecture and strange system design. Welcome everyone to follow my official account to communicate and communicate with me.

best relationship between , your likes is fried fish , thank you for your support.


煎鱼
8.4k 声望12.8k 粉丝