# Go 指针介绍

指针 (pointer) 持有一个值的内存地址。对指针操作修改值,会影响所有引用的值。

*T 定义指针变量。

var p *int

& 会生成一个指针类型的变量,它的值就是内存地址。

i := 42
p = &i

* 指针变量,取指针存的值。

fmt.Println(*p) // 42
*p = 21         // set i through the pointer p
func main() {
	i := 42
	var p *int
	p = &i

	fmt.Println(*p) // 42
	fmt.Println(p)  // 0xc00011c018
	fmt.Println(i)  // 42

	*p = 21 // 修改指针就相当于修改 i

	fmt.Println(*p) // 21
	fmt.Println(p)  // 0xc00011c018
	fmt.Println(i)  // 21

	// 修改 i,同样影响指针
	i = 404
	fmt.Println(*p) // 404
	fmt.Println(p)  // 0xc00011c018
	fmt.Println(i)  // 404
}

TIP

Go语言中的函数传参都是值拷贝,当我们想要修改某个变量的时候,我们可以创建一个指向该变量地址的指针变量。传递数据使用指针,而无须拷贝数据。

demoa2 是不会修改变量 i

type Demo struct {
	Name string
}

func main() {
	var i = Demo{
		Name: "qian",
	}
	demoa1(&i)
	fmt.Println(i)
	demoa2(i)
	fmt.Println(i)
}

func demoa1(d *Demo) {
	d.Name = "demoa1"
}
func demoa2(d Demo) {
	d.Name = "demoa2"
}

# Slice 的意外?

当不传 slice 的指针时候,是没办法对 i append 的。但可以修改 i 里面存在的 item

func main() {
	var i = []string{""}
	fmt.Println(i) // []
	Sum223(i)
	fmt.Println(i) // []
	Sum22(&i)
	fmt.Println(i) // [ Sum22 传的指针]
}

// 一样可以修改 arr 内容
func Sum223(arr []string) {
	arr = append(arr, "Sum22 传的指针")
}

func Sum22(arr *[]string) {
	*arr = append(*arr, "Sum22 传的指针")
}
func main() {
	var i = []string{"1", "2"}
	fmt.Println(i) // [1 2]
	demo1(i)
	fmt.Println(i) // [demo1 2]
	demo2(&i)
	fmt.Println(i) // [demo1 demo2]
}

// 一样可以修改 arr 内容
func demo1(arr []string) {
	arr[0] = "demo1"
}

func demo2(arr *[]string) {
	a := *arr
	a[0] = "demo2"
}

# 总结

var p *int // 定义指针变量
i := 42
p = &i 		// & 对变量取内存地址
*p = 21		// 修改指针变量的值,也会影响 i 的值。

所以只要遵循一条原则就不会错。

只要是想修改原来的参数,就传指针变量。