返回介绍

第二十九天

发布于 2023-06-25 22:22:03 字数 2983 浏览 0 评论 0 收藏 0

1.下面这段代码能否正常结束?

func main() {
    v := []int{1, 2, 3}
    for i := range v {
        v = append(v, i)
    }
}

参考答案及解析:不会出现死循环,能正常结束。 循环次数在循环开始前就已经确定,循环内改变切片的长度,不影响循环次数。

2.下面这段代码输出什么?为什么?

func main() {

    var m = [...]int{1, 2, 3}

    for i, v := range m {
        go func() {
            fmt.Println(i, v)
        }()
    }

    time.Sleep(time.Second * 3)
}

参考答案及解析:

2 3
2 3
2 3

for range 使用短变量声明(:=)的形式迭代变量,需要注意的是,变量 i、v 在每次循环体中都会被重用,而不是重新声明。

各个 goroutine 中输出的 i、v 值都是 for range 循环结束后的 i、v 最终值,而不是各个goroutine启动时的i, v值。可以理解为闭包引用,使用的是上下文环境的值。

两种可行的 fix 方法:

1.使用函数传递

for i, v := range m {
    go func(i,v int) {
        fmt.Println(i, v)
    }(i,v)
}

2.使用临时变量保留当前值

for i, v := range m {
    i := i           // 这里的 := 会重新声明变量,而不是重用
    v := v
    go func() {
        fmt.Println(i, v)
    }()
}

引自:https://tonybai.com/2015/09/17/7-things-you-may-not-pay-attation-to-in-go/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文