Golang中切片作为参数中的一些讨论

Golang中有多种变量类型,,值类型,引用类型,指针类型.每个类型作为参数传入都会有不同的结果

值类型无法被函数内部修改

引用类型和指针类型可以从函数内部修改变量

Slice是引用类型

在学习<<Go专家编程>>过程中,遇到这样一个题

func SliceRise(s []int) {
    s = append(s, 0)
    for i := range s {
       s[i]++
    }
}

func SliceRiseTest() {
    s1 := []int{1, 2}
    s2 := s1
    s2 = append(s2, 3) 
    SliceRise(s1)
    SliceRise(s2)
    fmt.Println(s1, s2)
}

 大家可以尝试看看打印输出什么





输出打印:

[1,2] [2,3,4]

下面来解释解释为什么会输出这样一个结果

首先s1 ->  len:2   cap:2

s2:=s1  此时s2,s1可以说完全一致,,,指向同一片内存空间

但是当  s2 = append(s2, 3)

s2发生了扩容,,为s2分配新的内存空间地址

此时 s1 ->  len:2   cap:2           s1 ->  len:3   cap:4

当执行SliceRise(s1)时

SliceRise内部得到一个s1的拷贝切片s,array指向相同的内存地址复制len,cap,进行append的操作,, s = append(s, 0) 这步操作后s -> len:3 > cap:2, 开辟新的内存空间,将新的内存地址赋给拷贝切片s,但是s1本身并没有被修改,所以后面的操作是对拷贝切片s(新开辟的内存空间)进行操作,无法对s1有影响,所以打印s1 :[1,2]

当执行SliceRise(s2)时,引用传递s2

SliceRise内部得到一个s2的拷贝切片s,array指向相同的内存地址,复制len,cap,进行append的操作,,,但array内存够用,此时s - >len:4,cap:4,,,所需后续进行对s进行的操作就相当于对s2进行的操作,,因为他们的底层数据地址是一样的.但是打印出来 s2: [2,3,4]

Slice结构体有三个字段

len和cap为值类型,array为引用类型,,,值类型无法从函数内部修改,,所以函数内部为4,4,,但是外部依旧为3,4

所以array依旧修改了,但是len相对内部,外部并没有被修改依旧是3,,也就是修改对于函数外部是无法被观测到的

我们可以尝试看看这个s2[3]这个位置是否依旧添加相应的元素,,代码如下

func SliceRise(s []int) {
	fmt.Printf("append before arr: %p\n", s)
	s = append(s, 0)
	fmt.Printf("append after arr: %p\n", s)

	for i := range s {
		s[i]++
	}
}

func SliceRiseTest() {
	s1 := []int{1, 2}
	s2 := s1
	s2 = append(s2, 3) //s2  与   s1  内存地址不在相同
	fmt.Printf("SliceRise Before s1: %p\n", s1)
	fmt.Printf("SliceRise Before s2: %p\n", s2)
	SliceRise(s1)
	SliceRise(s2)

	fmt.Printf("SliceRise After s1: %p\n", s1)
	fmt.Printf("SliceRise After s2: %p\n", s2)
	fmt.Println(s1, s2)
	s3 := s2[0:4] 
	fmt.Println(s3)
}

 输出结果

 哈哈,只是个人学习的一些见解,,,如有问题或者错误,请大家指正!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值