Go语言关于for range的案例分析

直接开始吧:

func main() {
	var a = [5]int{1, 2, 3, 4, 5}
	var r [5]int

	for i, v := range a {
		if i == 0 {
			a[1] = 12
			a[2] = 13
		}
		r[i] = v
	}
	fmt.Println("r = ", r)
	fmt.Println("a = ", a)
}

输出:

r =  [1 2 3 4 5]
a =  [1 12 13 4 5]

开始逐个分析:
首先定义了一个int类型的数组长度为5并对这个数组进行赋值,接着再定义了一个数组,长度也是5,不过这个没有赋值。然后是一个
for range ,我们知道for range的时候是一个原数据的副本,所以此时遍历的是只是a这个数组的值的副本,那既然只是值的副本那就跟a没有一毛钱关系了,所以遍历之后每次塞到 r 数组的值就是原来 a 数组的值,而a数组因为在i=0的时候修改了数据所以最终输出的是改过之后的值。
那就有个问题了,怎么才能让r 和 a数组的值一样呢?对,你猜对了。就是遍历的时候把 a 改成 a 的地址。

func main() {
	var a = [5]int{1, 2, 3, 4, 5}
	var r [5]int

	for i, v := range &a {
		if i == 0 {
			a[1] = 12
			a[2] = 13
		}
		r[i] = v
	}
	fmt.Println("r = ", r)
	fmt.Println("a = ", a)
}

输出:

r =  [1 12 13 4 5]
a =  [1 12 13 4 5]

咱们还是来看一下吧:
同样两个数组,a赋值了,r是个空的。接着看后面for range 一个 a 数组的指针类型,也就是说,就算是副本指针指向的位置和a 指向的地址也是一样的,所以a也被修改了。
也就是说,只要牵扯到修改值的问题,你就传指针,也就不用考虑那么多了。
接下来咱们看一下这种:

func main() {
	var a = []int{1, 2, 3, 4, 5}
	var r [5]int
	for i, v := range a {
		if i == 0 {
			a[1] = 12
			a[2] = 13
		}
		r[i] = v
	}
	fmt.Println("r = ", r)
	fmt.Println("a = ", a)
}

分析:首先定义一个切片类型a,并进行赋值,之后创建一个空数组r长度为5,同样的遍历a,但是这块跟之前的不一样,之前a是个数组,现在a是个切片,所以遍历的时候是a切片的副本,但是切片类型在go语言中其实就是一个结构体,里面包含三部分:1.指向底层数组的一个指针 2.切片长度 3.切片容量。那既然有指针,那就不用说了吧,就算是副本,改了也就是改了。所以别想那么多,输出肯定是这样的:

r =  [1 12 13 4 5]
a =  [1 12 13 4 5]

验证一下,确实是,完美。

总结:
1.for range的时候需要看一下遍历对象是什么,只要有指针,在遍历的时候改了就是改了,原数据也会改,如果只是值,那就没办法了,改了也是白改。
2.切片slice的底层其实是一个指向底层数组的一个指针,再加一个长度、一个容量。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值