1. 什么是指针
指针是存储内存地址的变量类型
2. 指针的声明与使用
指针的声明可以用一个已经存在的变量,也可以用 new(T) 的形式:
var num int = 5
p_num := &num
fmt.Printf("[%p] [%d]\n", p_num, *p_num) // 输出结果为:[0xc0000120a0] [5]
p_string := new(string)
*p_string = "It's Taco Tuesday, gi gi gi gi gi gi gi"
fmt.Println(*p_string)
可以看到,它的使用与大部分语言一样,用 & 来取地址,用 * 来解引用。
对于自定义类型,还有一种简便声明指针的方法:
type Human struct {
age int
name string
sex string
}
func (p Human) String() string {
return fmt.Sprintf("[Name: %s] [Age: %d] [Sex: %s]", p.name, p.age, p.sex)
}
func main() {
p := &Human{34, "James", "male"}
fmt.Println(*p) // 输出结果为:[Name: James] [Age: 34] [Sex: male]
}
上面的代码中,直接将结构体的初始化和指针的初始化写在一行了,是比较简洁的写法。
至于那个String()函数是怎么回事,fmt输出结果为什么是那样,在结构体一章会讲到。
4. 指针的零值
指针的零值是nil,不是NULL
5. 打印类型名称
打印类型名称用 %T 占位符:
n := 5
p_int := &n
fmt.Printf("[%T] [%T]\n", n, p_int) // 输出结果为:[int] [*int]
6. 指针数组和切片
指针数组可以做到在函数传参时,函数内部的操作改变原数组的元素,但这不是Go的惯用做法,Go为我们提供了切片,直接使用切片就好。
7. 指针运算
Go不支持指针的运算:
str := "Golang"
p_str := &str
//p_str++ // 无效的运算,编译报错
8. 实际应用 -- 实现自定义类型方法
在上面的Human结构体中,我们为Human类型定义了一个String()方法,func后面的(p Human)表示这个方法是Human类型的方法,这里如果不用指针,就是一个简单的值传递,不会改变原始数据,需要注意。