在 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) // 或者不使用指针
	}

}