Kenny
(LLLLLinux)
1
在发布 go 1.22 版本时,注意到了 for 循环有一个变更,简单就是说从之前的共享变量,调整为每次执行循环步都会重新实例化变量,这样避免了闭包中共享变量导致的并发问题。 于是今天通过代码模拟发生了一个令人困惑的问题,不同的执行方式,导致不同的结果,相同的代码:
func main() {
done := make(chan bool)
values := []string{"chen", "ming", "yong"}
for _, v := range values {
go func() {
fmt.Println(v)
done <- true
}()
}
// 结束前等待所有的 goroutine 执行成
for _ = range values {
<-done
}
}
当我使用 go run . 打印结果的时候为 (这显然是不正常的):
❯ go run .
yong
yong
yong
但是当我使用 go run main.go 打印结果确是正常的。这是为什么,是 bug 吗?还是本应该如此:
❯ go run main.go
yong
ming
chen
同时提交了 issue : import/path: Loops no longer share loop variablesRunning them in different ways gives different results · Issue #69704 · golang/go · GitHub
有没有大佬解答一下小弟的困惑
6 个赞
我拿你代码试下你提到的两种情况没区别啊,你是不第一次没保存
2 个赞
Kenny
(LLLLLinux)
4
保存了。应该是 go mod 的问题。我的 go mod 没有指定版本号。
1 个赞
确实,我把go.mod里面版本改到1.20之后结果和你主楼是一样的
2 个赞
Kenny
(LLLLLinux)
6
我感觉应该是 bug,我电脑只安装了 go 的一个版本。但是忽略了 go mod 的版本,应该使用最新的版本。
1 个赞
借楼问一个问题,golang的反序列化方法,假如这是一个待解析的json
{
“id”: “1”,
“name”: “2”,
“email”: “3”
}
那么json.Unmarshal的第二个参数应该要传递一个指针类型的map或者结构体,结构体传引用类型好理解,但是map本身就是引用类型,为什么还要传一个引用类型的map呢,这不是多次一举么,gpt给我回答的等于没回答…
dazuixia
(那不经意的想念)
9
你这语法本身就有问题. 需要用到 数组元素 都是 传参 进去的. 而不是 直接获取 外界变量的. 我5年go开发
1231
(䲜龘)
13
新特性如果go.mod中golang的版本比较低是不会生效的,一般通过go run好像是可以生效的
1 个赞
laosiji
(老司机)
14
go run . 会使用 go.mod 文件中的 go 版本来确定编译行为和标准库函数的使用。如果 go.mod
中没有指定 go
版本,Go 会选择一个默认的最低兼容版本来编译当前目录下的所有 main
包的文件。
go run main.go 也会使用 go.mod 中的版本来确定编译行为,但有时在没有 go.mod 的情况下,它可能使用当前环境中的 Go 编译器版本(即安装的 Go 版本)
go的1.23版本修改并发for对应的item问题,可能最低版本还是老版本所以全部打印一样数据
1 个赞
1231
(䲜龘)
15
我一般不会使用go run .这种写法,一般都是有个main.go的入口,其他的文件和main.go不放在一起,或者main.go需要使用多个同文件夹的go文件,使用go run *.go的方式
WhyNo
(WhyNo)
17
知道go run .和go run main.go的编译行为是有差异的,同时go mod文件中的go版本号会影响编译器的行为,但是具体不是很了解。
请问您描述的这个差异,能给一个官方文档的链接吗?
想学习一下,谢谢
laosiji
(老司机)
19
输入命令 go help run
有介绍如果没有mod指定版本将会使用什么样的顺序,第一个是自感知模块选取最低标准
可以试试
export GO111MODULE=off
go run .
和
export GO111MODULE=on
go run .
就可以看出效果,go文档有介绍自动寻版本顺序
2 个赞