大概代码如下
```golang
func main() {
old := make([]string, 0, 10)
fmt.Printf("old address: %p\n", old)
old = append(old, "one")
fmt.Printf("old address: %p\n", old)
add(old)
fmt.Println(old)
}
func add(temp []string) {
fmt.Printf("temp address: %p\n", temp)
temp = append(temp, "end")
fmt.Printf("temp address: %p\n", temp)
fmt.Println(temp)
}
结果如下:
old address: 0xc00009ad20
old address: 0xc00009ad20
temp address: 0xc00009ad20
temp address: 0xc00009ad20
[one end]
[one]
```
开始我make时故意将cap设置成10,就想它们共用一块内存, 从结果来看确实也是共用的一块,但old输出的值为何不是两个呢
哪个大侠对方面理解很深入的话帮忙解释一下吧,谢了
更多评论
go中函数的参数是值传递的,所以将old通过参数传递到add的temp的时候,其实创建了新的切片对象,新切片的内容复制了old切片的内容。这两个切片共享底层数组(重点,底层数组不会复制)。切片对象包括一个指针,一个len,以及一个cap。所以这里使用%p打印old和temp,其实打印的应该是切片对象中的指针部分,两个切片中指针部分是相同的,因为他们指向同一个底层数组(我刚学golang,没看过源码,这部分是猜的,原理应该是这样的)。如果你打印&old和&temp,就会发行不同的,说明old和temp是两个不同的切片对象。当`old = append(old, "one")`后,你打印old 和 &old[0] 应该是一样的。
当在add中通过`temp = append(temp, "end")`,向切片添加元素后,可以认为底层数组的第二个元素被设置为了`end`。temp切片此时的len是2,包涵两个元素,`one`和`end`。但是main函数中,old切片的len还是1,所以add函数返回后,打印old,其只会包涵一个元素`one`。但此时底层数组的第二个元素其实已经是`end`了,只是因为old切片的长度,第二个元素不在old切片中。所以在add函数中,你可以返回temp切片,将其重新赋值给old,应该就能达到你想要的效果了。
#1
// 更正一些注释<br/>
// 因为你在main函数里传递给add函数的应该是底层数组的地址,所以你的main函数无法得到正确的结果,可以通过返回值得到修改后的结果,或者修改形参,传变量的指针,以下代码两个函数都实现了你要的效果。<br/>
package main
import (
"fmt"
)
func main() {
old := make([]string, 0, 10)
fmt.Printf("old address: %p\n", old) //你打印地址的方式也不对
old = append(old, "one")
fmt.Printf("old address: %p\n", &old) //正确的方式
old = add(old)
fmt.Println("old=", old)
Add(&old)
fmt.Println("调用Add后 old=", old)
}
// add 传递的应该是底层数组的地址,可通过返回值得到操作后的结果
func add(temp []string) []string {
fmt.Printf("temp address1: %p\n", &temp) //传过来的地址跟main函数里不是同一地址
temp = append(temp, "end")
fmt.Printf("temp address2: %p\n", &temp) //传过来的地址跟main函数里不是同一地址
fmt.Println(temp)
return temp
}
// Add 传指针的方式,传递切片的指针
func Add(temp *[]string) {
fmt.Printf("temp address1: %p\n", *&temp) //传过来的地址跟main函数里的一致
*temp = append(*temp, "end")
fmt.Printf("temp address2: %p\n", *&temp) //传过来的地址跟main函数里的一致
fmt.Println(*temp)
}
#2