1.11 为什么传参使用切片而不使用数组?¶
Go里面的数组是值类型,切片是引用类型。
值类型的对象在做为实参传给函数时,形参是实参的另外拷贝的一份数据,对形参的修改不会影响函数外实参的值。
因此在如下例子中两次打印的指针地址是不一样的
package main
import "fmt"
func arrayTest (x [2]int) {
fmt.Printf("%p \n", &x) // 0xc0000b4030
}
func main() {
arrayA := [2]int{1,2}
fmt.Printf("%p \n", &arrayA) // 0xc0000b4010
arrayTest(arrayA)
}
假想每次传参都用数组,那么每次数组都要被复制一遍。如果数组大小有 100万,在64位机器上就需要花费大约 800W 字节,即 8MB 内存。这样会消耗掉大量的内存。
而引用类型,则没有这个拷贝的过程,实参与形参指向的是同一块内存地址
package main
import "fmt"
func sliceTest (x []int) {
fmt.Printf("%p \n", x)
}
func main() {
sliceA := make([]int, 0)
fmt.Printf("%p \n", sliceA)
sliceTest(sliceA)
}
由此我们可以得出结论:
把第一个大数组传递给函数会消耗很多内存,采用切片的方式传参可以避免上述问题。切片是引用传递,所以它们不需要使用额外的内存并且比使用数组更有效率。
那么你肯定要问了,数组指针也是引用类型啊,也不一定要用切片吧?
确实,传递数组指针是可以避免对值进行拷贝的内存浪费。