golang的值传递和引用传递

201 阅读1分钟

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 指针的地址, 这个非常重要!!!

参考:

www.cnblogs.com/wang_yb/p/1…