关于golang:goLang中range的注意小点

对于range应用时有个点须要留神一下,防止踩坑

平时应用range时都是这样
for i, element := range xxxx

有没有思考过element是如何赋值的?每次循环element是否是新生成长期变量?

先看看如下代码的运行后果

idNum := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}

waitGrp := sync.WaitGroup{}
for index, unit := range idNum {
    waitGrp.Add(1)

    fmt.Printf("unit(%d) addr:%p value:%d \n", index, &unit, unit)

    /*
        go func(num int) {
            fmt.Printf("------Num:%d, unit addr:%p \n", num, &num)
            waitGrp.Done()
        }(unit)
    */

    go func() {
        fmt.Printf("******Num:%d, unit addr:%p \n", unit, &unit)
        waitGrp.Done()
    }()
}

waitGrp.Wait()

输入后果如下

unit(0) addr:0xc0000ae040 value:0 
unit(1) addr:0xc0000ae040 value:1 
unit(2) addr:0xc0000ae040 value:2 
unit(3) addr:0xc0000ae040 value:3 
unit(4) addr:0xc0000ae040 value:4 
unit(5) addr:0xc0000ae040 value:5 
unit(6) addr:0xc0000ae040 value:6 
unit(7) addr:0xc0000ae040 value:7 
unit(8) addr:0xc0000ae040 value:8 
unit(9) addr:0xc0000ae040 value:9 
unit(10) addr:0xc0000ae040 value:10 
unit(11) addr:0xc0000ae040 value:11 
unit(12) addr:0xc0000ae040 value:12 
unit(13) addr:0xc0000ae040 value:13 
unit(14) addr:0xc0000ae040 value:14 
unit(15) addr:0xc0000ae040 value:15 
******Num:14, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:3, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:15, unit addr:0xc0000ae040 
******Num:10, unit addr:0xc0000ae040 

看第一局部输入

unit(0) addr:0xc0000ae040 value:0 
unit(1) addr:0xc0000ae040 value:1 
unit(2) addr:0xc0000ae040 value:2 
unit(3) addr:0xc0000ae040 value:3 
unit(4) addr:0xc0000ae040 value:4 
unit(5) addr:0xc0000ae040 value:5 
unit(6) addr:0xc0000ae040 value:6 
unit(7) addr:0xc0000ae040 value:7 
unit(8) addr:0xc0000ae040 value:8 
unit(9) addr:0xc0000ae040 value:9 
unit(10) addr:0xc0000ae040 value:10 
unit(11) addr:0xc0000ae040 value:11 
unit(12) addr:0xc0000ae040 value:12 
unit(13) addr:0xc0000ae040 value:13 
unit(14) addr:0xc0000ae040 value:14 
unit(15) addr:0xc0000ae040 value:15 

就能够明确了,element的地址是不变的,每次都是对同一个变量赋值的
所以在routine中间接拜访element时失去的是刹时以后的值。
如果想要在routine中应用每次循环的element值,将element值传入就能够了

go func(num int) {
    fmt.Printf("------Num:%d, unit addr:%p \n", num, &num)
            waitGrp.Done()
}(unit)

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理