golang本质上都是传值调用
func pointerParamRefTest() {
type Person struct {
Name string
Age int
}
var t3 = &Person{
Name: "test",
Age: 10,
}
var f3 = func(p *Person) {
p.Name = "test-change"
p.Age = 20
fmt.Printf("f3参数p指向的内存地址 = %p\n",p)
fmt.Printf("f3参数p的内存地址 = %p\n",&p)
}
fmt.Printf(">>>调用前: t3 = %v\n", t3)
fmt.Printf("t3指向的内存地址 = %p\n",t3)
fmt.Printf("t3的内存地址 = %p\n",&t3)
f3(t3) //t3和p是值传递,值的内容指向同一块内存
fmt.Printf("<<<调用后: t3 = %v\n", t3)
}
func sliceParamRefTest() {
var t4 = []string{"a", "b", "c"}
var f4 = func(p []string) {
fmt.Printf("f4参数p指向的内存地址 = %p\n",p)
fmt.Printf("f4参数p的内存地址 = %p\n",&p)
p[0] = "aa"
p = append(p, "d")
fmt.Printf("f4内部p指向的内存地址 = %p\n",p)
fmt.Printf("f4内部p的内存地址 = %p\n",&p)
}
fmt.Printf(">>>调用前: t4 = %v\n", t4)
fmt.Printf("t4指向的内存地址 = %p\n",t4)
fmt.Printf("t4的内存地址 = %p\n",&t4)
f4(t4)
fmt.Printf("<<<调用后: t4 = %v\n", t4)
}
func mapParamRefTest() {
var t5 = make(map[string]int)
t5["hello"] = 1
t5["world"] = 2
var f5 = func(p map[string]int) {
p["hello"] = 11
p["hello2"] = 22
fmt.Printf("f5参数p指向的内存地址 = %p\n",p)
fmt.Printf("f5参数p的内存地址 = %p\n",&p)
}
fmt.Printf(">>>调用前: t5 = %v\n", t5)
fmt.Printf("t5指向的内存地址 = %p\n",t5)
fmt.Printf("t5的内存地址 = %p\n",&t5)
f5(t5)
fmt.Printf("<<<调用后: t5 = %v\n", t5)
}
func main() {
//pointerParamRefTest()
//sliceParamRefTest()
mapParamRefTest()
}
总结:
对于普通类型(int, string 等等), 就是 传值 调用, 函数内对参数的修改, 不影响外面的变量
对于 struct 指针, slice 和 map 类型, 函数内对参数的修改之所以能影响外面, 是因为参数和外面的变量指向了同一块数据的地址
对于 struct 指针, slice 和 map 类型, 函数的参数和外面的变量的地址是不一样的, 所以本质上还是 传值 调用
slice 的 append 操作会改变 slice 指针的地址, 这个非常重要!!!
参考: