在 go 循环中,创建协程,协程内需要使用到外部变量,也可以通过 channel 传递参数,对于 channel 传递比较直接,这不做介绍了
本文主要记录,如何直接传递参数给协程,需要注意的问题
普通参数
func TestRoutineParam1(t *testing.T) {
for i := 0; i < 10; i++ {
go func() {
// 这里使用循环的局部变量 i,随着循环 i 在发生改变,协程最终都是最后一个 i=10
println(i)
}()
}
}
func TestRoutineParam2(t *testing.T) {
for i := 0; i < 10; i++ {
// 通过参数传递给协程,可以解决问题
go func(i int) {
println(i)
}(i)
}
}
func TestRoutineParam3(t *testing.T) {
for i := 0; i < 10; i++ {
// 通过赋值新的变量,可以解决问题
val := i
go func() {
println(val)
}()
}
}
使用到结构体
func TestRoutineParamPointer1(t *testing.T) {
type Model struct {
Data int `json:"data"`
}
res := []Model{
{
Data: 1,
},
{
Data: 2,
},
{
Data: 3,
},
}
for _, re := range res {
go func(re *Model) {
println(re.Data)
}(&re) // 如果这里获取局部变量的指针,遇到同样的问题,最终协程获取的始终是最后一个 Model
}
}
func TestRoutineParamPointer2(t *testing.T) {
type Model struct {
Data int `json:"data"`
}
res2 := []*Model{
{
Data: 1,
},
{
Data: 2,
},
{
Data: 3,
},
}
for _, re := range res2 {
go func(re *Model) {
println(re.Data)
}(re) // 如果数组遍历的是指针,直接传递指针没有问题
}
}
func TestRoutineParamPointer3(t *testing.T) {
type Model struct {
Data int `json:"data"`
}
res3 := []Model{
{
Data: 1,
},
{
Data: 2,
},
{
Data: 3,
},
}
for _, re := range res3 {
go func(re Model) {
println(re.Data)
}(re) // 或者不使用指针
}
}