指针是一个用来指示一个内存地址的变量,一个指针变量指向了一个值的内存地址。Go 语言也为我们提供了控制数据结构的指针的能力,同时不像 C/C++ 中指针那么灵活,在 Go 语言中我们不能进行指针运算。因此 Go 语言中指针相对比较容易学习。
语法
Go 语言的取地址符是 & ,放到一个变量前使用就会返回相应变量的内存地址。
var name Type = value// ①var p *Typep = &name// ②var p = &name// ③p := &name
对于变量 var 始终有 var == *(&var) 。在 fmt.Printf 函数中,指针的格式化标识符为 %p 。
package mainimport "fmt"func main() {var v = 5var p *intp = &vfmt.Printf("v: %d, p: %p\n", v, p)*p = v + 1fmt.Printf("v: %d, p: %p\n", v, p)}// 输出:// v: 5, p: 0xc00000a0c8// v: 6, p: 0xc00000a0c8
也可以使用 new 方法来创建指针变量: p := new(Type) ,例如:
str := new(string)*str = "Hello, pointer!"fmt.Println(*str)
指针的一个高级应用是你可以传递一个变量的引用(如函数的参数),这样不会传递变量的拷贝。指针传递是很廉价的,只占用 4 个或 8 个字节。当程序在工作中需要占用大量的内存,或很多变量,或者两者都有,使用指针会减少内存占用和提高效率。被指向的变量也保存在内存中,直到没有任何指针指向它们,所以从它们被创建开始就具有相互独立的生命周期。
限制
我们不能将指向 A 类型变量的指针赋值给 B 类型的指针变量:
var y float32 = 5.0var yP *intyP = &y // error: cannot use &y (type *float32) as type *int in assignment
不能得到一个文字或常量的地址,例如:
const i = 5ptr := &i //error: cannot take the address of iptr2 := &10 //error: cannot take the address of 10
不能对指针进行运算,来操作内存地址,例如: pointer + 2 、 c = *p++ 。Go 语言中的指针保证了内存安全,更像是 Java、C# 等语言中的引用。
空指针
当一个指针被定义后没有分配到任何变量时,它的值为 nil 。 nil 指针也称为空指针。 nil 在概念上和其它语言的 null 、 None 、 nil 、 NULL 一样,都指代零值或空值。
