Golang
goroutine是Go语言强大的特性之一,合理的利用它才能发挥最大的价值
1、经调查
发现初学者一般会犯以下错误使用goroutine
func goroutineRun(values []int) {
for value := range values {
go value.test()
}
}
或者使用闭包调用
func goroutineRun(values []int) {
for value := range values {
go func() {
fmt.Println(value)
}()
}
}
这2段代码实际上是遍历数组的所有变量。由于闭包只是绑定到这个value变量上,并没有被保存到goroutine栈中,所以以上代码极有可能运行的结构都输出为切片的最后一个元素。因为这样写会导致for循环结束后才执行goroutine多线程操作,这时候value值只指向了最后一个元素。这样的结果不是我们所希望的,而且还会产生并发的资源抢占冲突所以是非常不推荐这样写的。
2、解决方法
goroutine的正确写法
for val := range values {
go func(val interface{}) {
fmt.Println(val)
}(val)
}
在这里将 val 作为一个参数传入 goroutine 中,每个 val 都会被独立计算并保存到 goroutine 的栈中,从而得到预期的结果。
另一种方法是在循环内定义新的变量,由于在循环内定义的变量在循环遍历的过程中是不共享的,因此也可以达到同样的效果:
for i := range valslice {
val := valslice[i]
go func() {
fmt.Println(val)
}()
}