go语言切片深入讲解

我们在上一篇的切片讲解中,我们讲解到在go语言中 map和切片都是传引用(地址),也就是在调用函数的时候都是可以直接修改变量的值,关于切片,在某种程度上表面上来说也是可以这样说的,我们先来看一下一个小小的例题

1
2
3
4
5
6
7
8
9
10
11
package main
import "fmt"
func Change(s []int){
s[0]=11
s[1]=22
}
func main(){
slice:=[]int{1,2,3,4,5}
Change(slice)
fmt.Println(slice)
}

我们先来看一下结果

我们可以看到切片当作函数参数的时候调用之后值确实改变了,这也间接的可以认为切片是地址传递,但是我们想要了解的更深入的话可以继续了解下去 我们继续来看一个小例子

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"

func Add(s []int){
s=append(s,6,7,8)
}
func main(){
slice:=[]int{1,2,3,4,5}
Add(slice)
fmt.Println(slice)
}

在这里函数调用了append这个函数来增加切片的个数,

我们可以清晰的看到打印的结果并没有变,我们在之前讲到过这里是因为append扩容使得地址发生了变化,所以不是指向原来的切片也就导致了并不是在原来的切片上面增加了,这就说到了切片的本质,在这里详细说一下,切片的本质不是指向数组的指针,而是一种新定义的一种数据结构,这个数据结构里面包含一个指针,len,还有cap,

1
2
3
4
5
type slice struct {
*Pointer
len
cap
}

看到没,切片的本质是这样一个数据结构,而且在函数调用的时候切片做的其实是一个值的传递!!!只不过这个值是一个包含指针,长度,容量的一个结构体的值,这样我们一想就可以一目了然的知道了为什么前面我们所说的切片是地址传递了吧,那是因为他传的那个值里面包含一个指针,所以函数调用的时候就可以用这个值里面的指针来操作原来的切片,我们看如下的一张图片,

我们看上面的图就可以更加的明白了,在函数调用的时候首先,在栈区里面main函数会得到一块内存(栈帧),然后调用testFunc函数的时候testFunc也会得到一块内存(栈帧),然后调用的时候把切片的值传递给形参,注意这里的值是包含一个指针,长度,容量的结构体值,我们在使用一般操作的时候不会改变那个地址,所以会正常操作main函数里面的切片,当我们使用append函数的时候就会导致保存的指针值发生变化,那样就会保存一个新的地址,操作也会在新的地方操作,这样的话原来的切片就不会发生变化,当testFunc函数调用完毕后,我们的testFunc函数就会释放,而原来的切片也没有得到改变,这就是我们所看到的,这才是切片的本质 所以最后得到的总结就是:切片当作参数传递的时候是值传递,但是这个值不是一个普通的值,而是一个包含指针,长度,容量的值,如果有不懂的也可以尝试着去看一看源码。 附图:(内存的微讲解)

-------------本文结束感谢您的阅读-------------

本文标题:go语言切片深入讲解

文章作者:Wuman

发布时间:2018年09月03日 - 18:09

最后更新:2018年09月05日 - 12:09

原始链接:http://yoursite.com/2018/09/03/go语言切片深入讲解/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。