Go 1.22版本for循环特性更新

262 阅读1分钟

简介

对于老版本的for循环使用,有一个很经典的bug,就是每次循环的变量其实是同一个,后面的循环会更新覆盖前面变量的值。在发布的1.22版本中,修改成了每次迭代都创建新的变量,来规避之前并发情况下可能存在的问题;另外一个特性是支持整数类型直接for循环

示例

老版本(1.22之前)

之前的版本,go func(){}中打印的v变量结果都是c,也就for循环最后那次变量的值。

[xiaofeng@localhost gostudy]$ go version
go version go1.18.4 linux/amd64
[xiaofeng@localhost gostudy]$
[xiaofeng@localhost gostudy]$ cat main.go
package main

import "fmt"

func main() {
    done := make(chan bool)

    values := []string{"a", "b", "c"}
    for _, v := range values {
        go func() {
            fmt.Println(v)
            done <- true
        }()
    }

    // wait for all goroutines to complete before exiting
    for _ = range values {
        <-done
    }
}
[xiaofeng@localhost gostudy]$
[xiaofeng@localhost gostudy]$ go build main.go
[xiaofeng@localhost gostudy]$
[xiaofeng@localhost gostudy]$ ./main
c
c
c
[xiaofeng@localhost gostudy]$

处理方法也都是通过给go func(){}传参,打印的变量值结果是c、a、b(顺序随机是因为go func启动执行动态调度导致)。

[xiaofeng@localhost gostudy]$ cat main.go
package main

import "fmt"

func main() {
    done := make(chan bool)

    values := []string{"a", "b", "c"}
    for _, v := range values {
        go func(vp string) {
            fmt.Println(vp)
            done <- true
        }(v)
    }

    // wait for all goroutines to complete before exiting
    for _ = range values {
        <-done
    }
}
[xiaofeng@localhost gostudy]$
[xiaofeng@localhost gostudy]$ go build main.go
[xiaofeng@localhost gostudy]$
[xiaofeng@localhost gostudy]$ ./main
c
a
b

新版本

升级(使用root)

更新go版本到1.22.1。

[root@localhost Go]# wget https://golang.google.cn/dl/go1.22.1.linux-amd64.tar.gz
[root@localhost Go]# rm -rf /usr/local/go && tar -C /usr/local -xzf go1.22.1.linux-amd64.tar.gz
[root@localhost Go]# go version
go version go1.22.1 linux/amd64

验证变量特性

此时直接for循环,在go func(){}中打印的不再全是c,而是每次循环分别的值。

[root@localhost gostudy]# go version
go version go1.22.1 linux/amd64
[root@localhost gostudy]#
[root@localhost gostudy]# cat main.go
package main

import "fmt"

func main() {
    done := make(chan bool)

    values := []string{"a", "b", "c"}
    for _, v := range values {
        go func() {
            fmt.Println(v)
            done <- true
        }()
    }

    // wait for all goroutines to complete before exiting
    for _ = range values {
        <-done
    }
}
[root@localhost gostudy]#
[root@localhost gostudy]# go build main.go
[root@localhost gostudy]#
[root@localhost gostudy]# ./main
c
a
b

支持整型类型

另外,新版本支持整型类型进行for循环;而且是从0开始。

[root@localhost gostudy]# cat main.go
package main

import "fmt"

func main() {
        for i := range 3 {
                fmt.Println(i)
        }
}
[root@localhost gostudy]#
[root@localhost gostudy]# go build main.go
[root@localhost gostudy]#
[root@localhost gostudy]#
[root@localhost gostudy]# ./main
0
1
2