Go 中所有的 参数传递 都是值传递,是对数据进行一个拷贝。具体分为 引用类型和非引用类型。
非引用类型(值类型):int、string、float、bool
、数组和结构体
引用类型:指针、slice、map、channel、接口、函数等
变量存放的是一个内存地址值,这个地址值指向的空间存的才是真实值,内存通常在堆中分配,当没有任务变量引用这个地址时,该地址对应的数据空间就成了垃圾,被GC回收
这里所说的值传递,意思是引用类型在传递的时候,其实是将值的实际地址,也就是当前变量所在的地址拷贝一份进行传递。
数组和切片
深拷贝和浅拷贝
深拷贝 : 拷贝了一份一摸一样的,新数据的改动不会影响原数据的改动
浅拷贝 : 两个指向同一个地址,其中一个改了两个一起改
数组是深拷贝,切片是浅拷贝
值得注意的是 : 数组的长度也是数组类型的一部分,因此[5]int 和 [3]int 并非同一个类型,[3]int 也无法直接赋值给 [5]int
编译会报错:main.go:6: cannot use a (type [3]int) as type [5]int in assignment
如果将一个数组赋值给另一个变量b ,那么修改b并不会影响到a的内容!
同时将数组作为参数传递给函数,仍然是值传递,在函数中对(作为参数传入的)数组不会造成原数组的改变
但如果将切片作为参数传递给函数,虽然是值传递,但是指针始终指向同一个数组。因此将切片作为参数传给函数时,函数对该切片的修改在函数外部也是可以看到的!!
内存优化
切片保留对底层数组的引用。只要切片存在于内存中,数组就不能被垃圾回收。这在内存管理方面是值的关注的。
假设我们有一个非常大的数组,而我们只需要处理他的一小部分,为此我们创建这个数组的切片,并处理这个切片。但是这个数组仍然存在于内存中,因为切片正在引用他。
使用copy函数就可以切片的复制,这样就可以仅处理一部分且原来的大数组可以被GC回收