Golang for range关于切片的语法糖

转载自:https://blog.cyeam.com/golang/2018/10/30/for-interals

有以下代码:

func main() {
	v := []int{1, 2, 3}
	for i := range v {
		v = append(v, i)
	}
}

这个代码会遍历v的切片,在遍历的过程中append元素给切片,那么它会不会死循环呢?

答案是否定的,一下是for range的底层代码:

//   for_temp := range
//   len_temp := len(for_temp)
//   for index_temp = 0; index_temp < len_temp; index_temp++ {
//           value_temp = for_temp[index_temp]
//           index = index_temp
//           value = value_temp
//           original body
//   }

可以看到在一开始切片的长度就已经被获取了,所以最终是做了切片的长度(3次)的循环

再看一段代码:

func main() {
	slice := []int{0, 1, 2, 3}
	myMap := make(map[int]*int)

	for index, value := range slice {
		myMap[index] = &value
		fmt.Println(&value)
	}
	fmt.Println("=====new map=====")
	for k, v := range myMap {
		fmt.Printf("%d => %d\n", k, *v)
	}
}

这段代码定义了一个key为int,value为*int的map,想要把切片的index与其指向元素的地址传进去,,结果会发现输出的三个元素数值是相同的,都为最后的元素3:

=====new map=====
0 => 3
1 => 3
2 => 3
3 => 3

造成这种情况的原因是for range返回的这个value并不是切片本身的value,而是其value的一个复制,因为:再golang中大多数的函数都是值传递而不是指针传递,在传递过程中会对变量进行一次复制,以保证原数据不会被其他行为修改。所以,存放在map中的都是一个复制过后的变量而非切片原来的元素,而这个变量又是全局变量,它的地址是始终不变的,改变的只是它所指向的数值,因为数值改变而地址不变,所以这种写法会出现这种错误,但是如果在map中不存在指针而是存放数值就没有问题了:

func main() {
	slice := []int{0, 1, 2, 3}
	myMap := make(map[int]int)

	for index, value := range slice {
		myMap[index] = value
		fmt.Println(&value)
	}
	fmt.Println("=====new map=====")
	for k, v := range myMap {
		fmt.Printf("%d => %d\n", k, v)
	}
}

输出为:

0xc000058080
0xc000058080
0xc000058080
0xc000058080
=====new map=====
0 => 0
1 => 1
2 => 2
3 => 3

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值