Go for range常见的坑
2012 年 8 月 22 日
在日常开发中, for range
肯定是经常用到的,下面我整理了一些自己平常会遇到的坑
首先第一个肯定是遍历 slice
的坑了
func main() { arr := []int{1, 2, 3} newArr := []*int{} for _, v := range arr { newArr = append(newArr, &v) } for _, v := range newArr { fmt.Println(*v) } } // 输出 3 3 3
之所以会输出 3 3 3
是因为 for range
在循环时, go
会创建一个额外的变量去存储循环的元素,所以在每一次迭代中,该变量都会被重新赋值,由于这里使用的是指针,所以就出现上面的这种情况。我们可以用 &arr[i]
去替代 &v
下面是一个在循环体内修改遍历的对象的场景
func main() { a := []int{1,2,3} for _, v := range a { a = append(a, v) } fmt.Println(a) } // 输出 [1 2 3 1 2 3]
之所以只输出两遍 1 2 3
而不是一直循环下去,是因为 for range
在编译期间,就会把 a
赋值给一个新的变量,所以我们遍历的其实已经不是 a
变量了。
遍历 map
,无序的场景
func main() { m := map[int]struct{}{ 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, } for k := range m { fmt.Println(k) } } // 输出不定
map
在遍历时,起始遍历索引是一个随机数,所以这里的输出结果是不能确定的
遍历 map
时删除元素
func main() { m := map[int]struct{}{ 1:{}, 2:{}, 3:{}, 4:{}, 5:{}, } count := 0 for range m { if count == 0 { delete(m, 5) } count++ } fmt.Println(count) } // 输出 4或5
这种输出的原因可以从上个例子中找到