golang中range问题

示例代码

package main

import (
    "fmt"
    "time"
)
type newField string

func (f newField) print() {
    fmt.Println(f)
}

func main() {
    data := []newField{"one", "two", "thred"}
    for _, v := range data {
        go v.print() //print one two three
        go func(){fmt.Println(v)}() // print three three three
    }
    time.Sleep(3 * time.Second)
}

疑问

range过程中,两种打印方式,为什么打印的结果不同呢?

阅读 2k
2 个回答

闭包的问题,v.print()是依次调用的是"one","two","three"的print方法。第二个goroutine引用了循环变量v,goroutine未启动时,v就改变了,所以不一致,但是不一定是three,three,three,与运行时的调度有关

经典的 golang for-range 陷阱。Google 下就知道了

func main() {
    data := []newField{"one", "two", "thred"}
    for _, v := range data {
        tmp := v
        go func(){fmt.Println(tmp)}()
        go func(){fmt.Println("addr:", &v, ", value:", v)}() // print three three three
    }
    time.Sleep(3 * time.Second)
}

可以运行下这个程序。 go v.print() 等同于赋值后,再执行 Println。“v” 的地址一直没变,所以打印出来的都是最后一次的赋值,即"three"

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题