Go语言为程序员提供了控制数据结构指针的能力,但是并不能进行指针运算。
如果一个变量声明var x int,表达式&x(x的地址)获取一个指向整型变量的指针,它的类型是整型指针(*int)。如果值叫作p,我们说p指向x,或者p包含x的地址。p指向的变量写成*p,表达式*p获取变量的值,一个整型,因为*p代表一个变量。
三个概念:指针地址、指针类型和指针取值
1、当一个指针被定义后没有分配到任何变量时,它的默认值为 nil,经常出现 panic: runtime error: invalid memory address or nil pointer dereference,这是典型的Go 指针声明后没有对指针先初始化而直接赋值导致的错误。
//nil判断
var p1, p2 int
fmt.Println(&p1 == &p1) //取指针地址,同一变量地址一样
fmt.Println(&p1 == &p2) //取指针地址,两者不一样
fmt.Println(&p1 == nil) //false
//指针类型的零值为nil
var p3 *int
fmt.Println(p3 == nil) //true
p4 := new(int) //*int 类型的p,指向未命名的int变量
fmt.Println(*p4) // 0
*p4 = 2
fmt.Println(*p4) //2
var p5 *int //初始化指针,指针有了自己的地址(指针地址),但还没有值的地址(值地址),即i为nil
//p5 = new(int)//new初始化值的内存地址,预先分配一个内存地址到指针
*p5 = 2 //报错
2、一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。
3、Go语言中使用在变量名前面添加&操作符(前缀)来获取变量的内存地址(取地址操作),提示:变量、指针和地址三者的关系是,每个变量都拥有地址,指针的值就是地址。
// v 的类型为 T,其中 v 代表被取地址的变量,变量 v 的地址使用变量 ptr 进行接收,ptr 的类型为*T,称做 T 的指针类型,*代表指针。
ptr := &v
4、当使用&操作符对普通变量进行取地址操作并得到变量的指针后,可以对指针使用*操作符,也就是指针取值
5、取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值
附代码:
func main(){
var intNum int = 6
p := &intNum
fmt.Println(*p)
//p 类型
fmt.Printf("p type: %T\n", p)
//p 指针类型
fmt.Printf("p address: %p\n", p)
//取值
val := *p
fmt.Printf("p VAL type: %T\n", val)
fmt.Printf("p VAL: %d \n", val)
//修改值
*p = 5
fmt.Println(*p) //5
fmt.Println(intNum) //5
//用作参数 + 10
sum(&intNum)
fmt.Println(*p) //15
fmt.Println(intNum) //15
}
//指针运算,参数类型为 *int 指针类型
func sum(ptr *int) {
*ptr = *ptr + 10
}