go loop,defer 和 闭包

golang 中的陷阱. 这是一个有趣的例子,用到了 loop, defer 和闭包.

例子 1,输出全是 5, 例子 2 和例子 3 会输出 5 4 3 2 1 0.

// 1
package main

import "fmt"

func main() {
    var whatever [6]struct{}
    for i := range whatever {
        defer func() {
            fmt.Println(i)
        }()
    }
    /*
        为什么全是 5,为什么不是 0, 1, 2, 3, 4, 5 这样的输出结果呢?

        其根本原因是闭包所导致的,有两点原因:

        1. 在 for 循环结束后,局部变量 i 的值已经是 5 了,并且 defer 的闭包是直接引用变量的 i。
        2. 结合defer 关键字的特性,可得知会在 main 方法主体结束后再执行。
        结合上述,最终输出的结果是已经自增完毕的 5。

    */
}

//2
package main

import "fmt"

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

//3
package main

import "fmt"

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

defer 执行顺序是先进后出的倒序执行.

例子 2 中用局部变量声明的方式把的值拷克了.因此输出结果和例子 1 不同.

例子 3 中,defer 执行的函数的参数是由声明时确定的.因此输出结果和例子 1 不同.

来源: https://eddycjy.com/posts/go/go-tips-defer/

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.