slice作为函数参数是值传递
golang中的切片slice底层通过数组实现,slice类似一个结构体,其中一个字段保存的是底层数组的地址,还有长度(len) 和 容量(cap)两个字段。
结构体作为函数参数时是值拷贝,同理,实际上slice作为函数参数时也是值拷贝,在函数中对slice的修改是通过slice中保存的地址对底层数组进行修改,所以函数外的silce看起来被改变了。
当需要对slice做插入和删除时,由于需要更改长度字段,值拷贝就不行了,需要传slice本身在内存中的地址。
以删除为例,说明这种情况。
不通过函数,直接删除slice中的一个元素
package main
import "fmt"
func main() {
si := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Printf("%v len %d \n", si, len(si))
si = append(si[:3],si[4:]...)
fmt.Printf("%v len %d \n", si, len(si))
}
// ---------输出结果-------------------
[1 2 3 4 5 6 7 8 9] len 9
[1 2 3 5 6 7 8 9] len 8
// --------成功删除了4 长度减1---------
通过函数,参数是slice变量
func main() {
si := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Printf("%v len %d \n", si, len(si))
test1(si)
fmt.Printf("%v len %d \n", si, len(si))
}
func test1(si []int) {
si = append(si[:3], si[4:]...)
}
// -------------输出结果-------------------
[1 2 3 4 5 6 7 8 9] len 9
[1 2 3 5 6 7 8 9 9] len 9
// -----4虽然被删除了,但是长度不变,最后面还多了个9,可见不是想要的结果
通过函数,参数是slice变量的地址
func main() {
si := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Printf("%v len %d \n", si, len(si))
test(&si)
fmt.Printf("%v len %d \n", si, len(si))
}
func test(si *[]int) {
(*si) = append((*si)[:3], (*si)[4:]...)
}
// ---------输出结果-------------------
[1 2 3 4 5 6 7 8 9] len 9
[1 2 3 5 6 7 8 9] len 8
// --------成功删除了4 长度减1---------