以下这样的循环代码,最后会发现spaceId都是同一个!!!!
for _, spaceId := range spaceIds {
task := func() {
uc.log.WithContext(ctx).Errorf("SpaceUsecase::GetSpaces uc.badgeClt.Get spaceId:%v start!!!!", spaceId)
}
getBadgesTasks = append(getBadgesTasks, task)
}
这是因为在任务函数 task
中,spaceId
是一个外部变量,它在任务函数被创建时捕获了当前循环迭代的值。这种情况被称为“循环变量捕获”,是 Go 语言中的一个常见陷阱。
在循环中启动 goroutine 时,如果不采取特定的措施,那么所有 goroutine 都会共享同一个循环变量,最终会导致它们所有的 spaceId
都是相同的。在这个例子中,由于 task
函数被添加到 getBadgesTasks
切片中,因此每次调用 task
时,都会使用相同的 spaceId
值。
为了避免这个问题,可以将循环变量的值传递给任务函数作为参数,从而使每个 goroutine 都有自己的 spaceId
值。例如:
for _, spaceId := range spaceIds {
task := func(spaceId int32) {
// 在函数内使用 spaceId 参数
// ...
}
getBadgesTasks = append(getBadgesTasks, func() { task(spaceId) })
}
在这种情况下,每个任务函数都会创建一个新的闭包,其中 spaceId
的值被捕获并传递给任务函数的参数,在每次迭代时都会创建一个新的闭包和参数。这样,每个 goroutine 都会有自己的 spaceId
值,可以避免相互影响的问题。