Go for range常见的坑

198 阅读1分钟

在日常开发中,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

这种输出的原因可以从上个例子中找到