乐趣区

关于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)
退出移动版