切片内部结构:
struct Slice { byte* array; // actual data uintgo len; // number of elements uintgo cap; // allocated number of elements };
第一个字段表示 array 的指针,是真实数据的指针第二个是表示 slice 的长度,第三个是表示 slice 的容量。
所以 unsafe.Sizeof(切片)永远都是 24。
当把 slice 作为参数,本身传递的是值,但其内容就 byte* array,实际传递的是引用,所以可以在函数内部修改,但如果对 slice 本身做 append,而且导致 slice 进行了扩容,实际扩容的是函数内复制的一份切片,对于函数外面的切片没有变化。
package main import ( "fmt" "unsafe" ) func main() { slice_test := []int{1, 2, 3, 4, 5} fmt.Println(unsafe.Sizeof(slice_test)) fmt.Printf("main:%#v,%#v,%#v\n", slice_test, len(slice_test), cap(slice_test)) slice_value(slice_test) fmt.Printf("main:%#v,%#v,%#v\n", slice_test, len(slice_test), cap(slice_test)) slice_ptr(&slice_test) fmt.Printf("main:%#v,%#v,%#v\n", slice_test, len(slice_test), cap(slice_test)) fmt.Println(unsafe.Sizeof(slice_test)) } func slice_value(slice_test []int) { slice_test[1] = 100 // 函数外的slice确实有被修改 slice_test = append(slice_test, 6) // 函数外的不变 fmt.Printf("slice_value:%#v,%#v,%#v\n", slice_test, len(slice_test), cap(slice_test)) } func slice_ptr(slice_test *[]int) { // 这样才能修改函数外的slice *slice_test = append(*slice_test, 7) fmt.Printf("slice_ptr:%#v,%#v,%#v\n", *slice_test, len(*slice_test), cap(*slice_test)) }
结果如下:
24 main:[]int{1, 2, 3, 4, 5},5,5 slice_value:[]int{1, 100, 3, 4, 5, 6},6,10 main:[]int{1, 100, 3, 4, 5},5,5 slice_ptr:[]int{1, 100, 3, 4, 5, 7},6,10 main:[]int{1, 100, 3, 4, 5, 7},6,10 24
实例:
package main import "fmt" func main() { var array = []int{1, 2, 3, 4, 5} printSlice(array) slice := array[1:] printSlice(slice) array[1] = 100 printSlice(slice) } func printSlice(x []int){ fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x) }
以上代码执行输出结果为:
len=5 cap=5 slice=[1 2 3 4 5] len=4 cap=4 slice=[2 3 4 5] len=4 cap=4 slice=[100 3 4 5]
使用 copy 函数要注意对于 copy(dst, src),要初始化 dst 的 size,否则无法复制。
错误示例:
dst := make([]int, 0) src := []int{1, 2, 3} copy(dst, src) printSlice(src) printSlice(dst) func printSlice(x []int){ fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) }
输出结果:
len=3 cap=3 slice=[1 2 3] len=0 cap=0 slice=[]
正确示例:
dst := make([]int, 3) // 令size=3 src := []int{1, 2, 3} copy(dst, src) printSlice(src) printSlice(dst)
len=3 cap=3 slice=[1 2 3] len=3 cap=3 slice=[1 2 3]
append() 和 copy() 部分,貌似有没说明白的地方。
当 numbers = [0, 1] 时,append(numbers, 2, 3, 4) 为什么 cap 从 2 变成 6 ?
经过实践得知,append(list, [params]),先判断 list 的 cap 长度是否大于等于 len(list) + len([params]),如果大于那么 cap 不变,否则 cap 等于 max{cap(list), cap[params]},所以当 append(numbers, 2, 3, 4) cap 从 2 变成 6。
在做函数调用时,slice 按引用传递,array 按值传递:
package main import "fmt" func main(){ changeSliceTest() } func changeSliceTest() { arr1 := []int{1, 2, 3} arr2 := [3]int{1, 2, 3} arr3 := [3]int{1, 2, 3} fmt.Println("before change arr1, ", arr1) changeSlice(arr1) // slice 按引用传递 fmt.Println("after change arr1, ", arr1) fmt.Println("before change arr2, ", arr2) changeArray(arr2) // array 按值传递 fmt.Println("after change arr2, ", arr2) fmt.Println("before change arr3, ", arr3) changeArrayByPointer(&arr3) // 可以显式取array的 指针 fmt.Println("after change arr3, ", arr3) } func changeSlice(arr []int) { arr[0] = 9999 } func changeArray(arr [3]int) { arr[0] = 6666 } func changeArrayByPointer(arr *[3]int) { arr[0] = 6666 }
输出结果为:
before change arr1, [1 2 3] after change arr1, [9999 2 3] before change arr2, [1 2 3] after change arr2, [1 2 3] before change arr3, [1 2 3] after change arr3, [6666 2 3]
感谢您的支持,我会继续努力的!
支付宝扫一扫,即可进行扫码打赏哦
2160Go 语言切片(Slice)
切片内部结构:
第一个字段表示 array 的指针,是真实数据的指针第二个是表示 slice 的长度,第三个是表示 slice 的容量。
所以 unsafe.Sizeof(切片)永远都是 24。
当把 slice 作为参数,本身传递的是值,但其内容就 byte* array,实际传递的是引用,所以可以在函数内部修改,但如果对 slice 本身做 append,而且导致 slice 进行了扩容,实际扩容的是函数内复制的一份切片,对于函数外面的切片没有变化。
结果如下:
2159Go 语言切片(Slice)
实例:
以上代码执行输出结果为:
2158Go 语言切片(Slice)
使用 copy 函数要注意对于 copy(dst, src),要初始化 dst 的 size,否则无法复制。
错误示例:
输出结果:
正确示例:
输出结果:
2157Go 语言切片(Slice)
append() 和 copy() 部分,貌似有没说明白的地方。
当 numbers = [0, 1] 时,append(numbers, 2, 3, 4) 为什么 cap 从 2 变成 6 ?
经过实践得知,append(list, [params]),先判断 list 的 cap 长度是否大于等于 len(list) + len([params]),如果大于那么 cap 不变,否则 cap 等于 max{cap(list), cap[params]},所以当 append(numbers, 2, 3, 4) cap 从 2 变成 6。
2156Go 语言切片(Slice)
在做函数调用时,slice 按引用传递,array 按值传递:
输出结果为: