func main() {
s2 := make([]int, 0, 10)
fmt.Printf("%p\n", s2)
addValue(s2)
fmt.Println(s2)
}
func addValue(list []int) {
fmt.Printf("%p\n", list)
list = append(list, 1, 2, 3, 4)
fmt.Println(list)
fmt.Printf("%p\n", list)
}
最后打印出的结果是:
0x140000b4000
0x140000b4000
[1 2 3 4]
0x140000b4000
[]
为什么 s2 和 list 指向的地址相同,保存的值不同呢
1
mainjzb 2022-02-14 10:50:04 +08:00
func addValue(list []int) []int{
fmt.Printf("%p\n", list) list = append(list, 1, 2, 3, 4) fmt.Println(list) fmt.Printf("%p\n", list) return list } |
2
hujun528 2022-02-14 10:58:33 +08:00
|
3
nulIptr 2022-02-14 11:00:48 +08:00 2
因为 slice 除了起始地址之外还保存了长度,你 main 函数里面的 s2 长度还是 0 ,长度还是 0 的原因的参数是值传递,addValue 里面修改的是拷贝一次的 slice 结构,而不是 main 函数里的 s2
|
4
shyz 2022-02-14 11:12:07 +08:00
函数都是值拷贝,sli 是引用类型,list 拷贝了 sli 的地址,直接输出地址肯定一样了。
|
5
monetto 2022-02-14 11:18:35 +08:00 3
可以这样理解,一个 slice 实际是一个 []int + 长度。
你在函数里 addValue 之后,数组的下一位其实是赋值成功的。(如果没有触发 Slice 重新分配数组内存) 但是,长度是 “形参” ,函数内的改变不会影响函数外部。 也就是说,其实整个过程,是赋值成功的,但是,由于长度没有发生变化,addValue 外部的逻辑无法感知到新添加的元素。 想要验证的话,可以通过 unsafe 获取 addValue 添加元素的地方的那块内存,会发现实际是添加成功了的。 顺便一提,如果 addValue 的过程中,数组的长度达到阈值了,那么就会触发 Slice 重新分配内存,这个时候,传入函数中的 那个时刻的那个 数组 ,实际上是没有任何变化的。 |
8
hujun528 2022-02-14 11:37:49 +08:00 1
package main
import ( "fmt" "testing" ) func Test_test33(T *testing.T) { test33() } func test33() { s2 := make([]int, 2, 10) //初始长度 2 s2 = append(s2, 66, 88) //长度+2 fmt.Println(s2) //s2 总长度 =4 fmt.Printf("%p\n", s2) addValue(s2) //传递 切片底向的 底层数组 针针 fmt.Println(s2) //s2 总长度 4 并没有改变 s2 = s2[:8] //如果改变切片 s2 的长度 =list 长度, fmt.Println(s2) // 是不是和 list 输出一样了 } func addValue(list []int) { fmt.Printf("%p\n", list) //此切片 list 并不完全等于 切片 s2,切片之间也是无法进行比较的,list 只是和 s2 共用同一底层数组 ,切片 还有长度和容量 list = append(list, 1, 2, 3, 4) //list 长度 +4 ,此操作 并不会改变 s2 的切片长度 fmt.Printf("%p\n", list) fmt.Println(list) } |
9
iyear 2022-02-14 11:39:27 +08:00 via Android 2
|
10
wheeler 2022-02-14 12:22:03 +08:00 via iPhone
go slice 的 api 太不直观了。好像是肯汤普森写的。
|
11
WhereverYouGo 2022-02-14 13:02:24 +08:00
@iyear #9 博客不错
|
12
CEBBCAT 2022-02-14 13:12:56 +08:00
Go 博客可以多读一读 https://go.dev/blog/slices-intro
|
13
ryalu 2022-02-14 13:43:50 +08:00
|
14
lpxxn 2022-02-14 16:31:20 +08:00
|
15
Lexgni 2022-02-14 17:47:47 +08:00
你的 len 是 0 ,然后你追加的话原来的放不下,就会重新分配一个,你打印一下追加后的 list 就会发现和前面不一样了
|