登录
首页 >  Golang >  Go问答

如何同步 go 例程以同时初始化切片?

来源:stackoverflow

时间:2024-04-08 20:30:38 482浏览 收藏

积累知识,胜过积蓄金银!毕竟在Golang开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《如何同步 go 例程以同时初始化切片?》,就带大家讲解一下知识点,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~

问题内容

我正在尝试使用 go 例程以并发方式初始化项目数组。然而,go 奇怪的内存行为阻止我这样做,即使我使用了建议的原语(通道)。以下是最小重现:

func TestSliceInit(t *testing.T){
toInit := make([]int, 10)
syncLock := make(chan bool)

for i := range toInit{
    go func(){toInit[i] = i; syncLock <- true}()
}

for range toInit{
    <-syncLock
}

for i := range toInit{
    if toInit[i] != i{
        t.Error("fail to init")
    }
}
}

代码应该将 toinit 数组初始化为 0-9,但事实并非如此。相反,会产生错误。我在 goland 2018.1 上尝试了这段代码


解决方案


因为代码是并发运行的,所以每次调用 goroutine 时,变量 i 都会被修改,因为它们都保留对同一变量 i 的引用

为了防止这种情况发生,请将索引参数传递给您的匿名函数。

package main

import "fmt"

func main() {
  toinit := make([]int, 10)
  synclock := make(chan bool)

for i := range toinit{
    go func(i int){
      toinit[i] = i; 
      synclock <- true}(i)
}

for range toinit{
    <-synclock
}

for i := range toinit{
    if toinit[i] != i{
        fmt.println("error")
    }
}
}

另一种方法是使用以下声明样式

for i := range toInit{
        i := i
        go func(){
          toInit[i] = i; 
          syncLock <- true}()
 }

这是一个关于 closures and goroutines 的很好的文档

理论要掌握,实操不能落!以上关于《如何同步 go 例程以同时初始化切片?》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>