Loop 是日常开发过程中经常遇到的问题,但是其中也有一些注意点需要关注。
循环中使用闭包
现由如下代码:
func TestFunBiBao(t *testing.T) {
data := []string{"one", "two", "three"}
for _, v := range data {
go func() {
fmt.Println(v)
}()
}
time.Sleep(3 * time.Second)
//goroutines print: three, three, three
}
我们可能会预期输出结果是:
one
two
three
然而实际
=== RUN TestFunBiBao
three
three
three
--- PASS: TestFunBiBao (3.00s)
PASS
case 2 LOOP中对元素是指针类别的数组(slice)进行append操作,须确保append对象的指针在LOOP被正确更新
对数据循环进行增添元素, 需确保有更新效性
type Object struct {
Index int
}
//targetList的元素.Index 的输出结果: [9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
func TestObjLoop(t *testing.T) {
var targetList []*Object // 指针类型的
var pObj *Object
pObj = &Object{}
for loopCnt := 0; loopCnt < 10; loopCnt++ {
pObj.Index = loopCnt
targetList = append(targetList, pObj)
}
for _, obj := range targetList {
fmt.Println(obj.Index)
}
}
实际输出结果是:
=== RUN TestObjLoop
9
9
9
9
9
9
9
9
9
9
--- PASS: TestObjLoop (0.00s)
PASS
正确的写法
// targetList的元素.Index 的输出结果: [0,1,2,3,4,5,6,7,8,9]
func TestObjLoop_1(t *testing.T) {
var targetList []*Object // 指针类型的
for loopCnt := 0; loopCnt < 10; loopCnt++ {
var pObj *Object // 循环内新建对象,确保指针更新
pObj = &Object{}
pObj.Index = loopCnt
targetList = append(targetList, pObj)
}
for _, obj := range targetList {
fmt.Println(obj.Index)
}
}
执行结果:
=== RUN TestObjLoop_1
0
1
2
3
4
5
6
7
8
9
--- PASS: TestObjLoop_1 (0.00s)
PASS
case 3:
func TestObjLoop_2(t *testing.T) {
var targetList []Object // 指针类型的
var pObj Object
pObj = Object{}
for loopCnt := 0; loopCnt < 10; loopCnt++ {
pObj.Index = loopCnt
targetList = append(targetList, pObj)
}
for _, obj := range targetList {
fmt.Println(obj.Index)
}
}
实际执行结果:
=== RUN TestObjLoop_2
0
1
2
3
4
5
6
7
8
9
--- PASS: TestObjLoop_2 (0.00s)
PASS
如果是 指针类型,要特别注意。