Go语言指针详解
例如:变量 b 的值为 156,存储在内存地址 0x1040a124。变量 a 持有变量 b 的地址,则变量 a 被认为指向变量 b。如下图所示。

图:指针变量
在Go语言中使用取地址符(&)来获取变量的地址,一个变量前使用&,会返回该变量的内存地址,示例代码如下所示。
package main import "fmt" func main() { a := 10 fmt.Printf("变量的地址为:%x \n", &a) }运行结果如下:
变量的地址为:c00000c198
注意:在不同的环境下输出结果可能不同。
Go语言指针的特点如下:- Go语言指针的最大特点是:指针不能运算(不同于C语言);
- 在Go语言中如果对指针进行运算会报错,如下所示。
- nvalid operation: p++ (non-numeric type *int)
1、声明指针
声明指针,*T 是指针变量的类型,它指向 T 类型的值,语法格式如下。var 指针变量名 *指针类型
其中,*
用于指定变量是一个指针。
var ip *int // 指向整型的指针
var fp *float32 // 指向浮点型的指针
- 定义指针变量;
- 为指针变量赋值;
- 访问指针变量中指向地址的值。
获取指针指向的变量值,只需要在指针类型的变量前加上 * 号(前缀),如 *a。示例代码如下所示。
package main import "fmt" func main() { //声明实际变量 var a int = 120 //声明指针变量 var ip *int //给指针变量赋值,将变量 a 的地址赋值给 ip ip = &a // 打印 a 的类型和值 fmt.Printf("a 的类型是:%T,值是:%v \n", a, a) // 打印 &a 的类型和值 fmt.Printf("&a 的类型是:%T,值是:%v \n", &a, &a) // 打印 ip 的类型和值 fmt.Printf("ip 的类型是:%T,值是:%v \n", ip, ip) // 打印 *ip 的类型和值 fmt.Printf("*ip 的类型是:%T,值是:%v \n", *ip, *ip) // 打印变量 *&a 的类型和值 fmt.Printf("*&a 的类型是:%T,值是:%v \n", *&a, *&a) fmt.Println(a, &a, *&a) fmt.Println(ip, &ip, *ip, *(&ip), &(*ip)) }运行结果如下:
a 的类型是:int,值是:120
&a 的类型是:*int,值是:0xc00000c198
ip 的类型是:*int,值是:0xc00000c198
*ip 的类型是:int,值是:120
*&a 的类型是:int,值是:120
120 0xc00000c198 120
0xc00000c198 0xc000006028 120 0xc00000c198 0xc00000c198
package main import "fmt" type Student struct { name string age int married bool sex int8 } func main() { var s1 = Student{"Steven", 35, true, 1} var s2 = Student{"Sunny", 20, false, 0} var a *Student = &s1 //将s1的内存地址赋值给student指针变量a var b *Student = &s2 //将s2的内存地址赋值给student指针变量b fmt.Printf("s1类型为 %T, 值为 %s \n", s1, s1) fmt.Printf("s2类型为 %T, 值为 %v \n", s2, s2) fmt.Printf("a类型为 %T, 值为 %v \n", a, a) fmt.Printf("b类型为 %T, 值为 %v \n", b, b) fmt.Printf("*a类型为 %T, 值为 %v \n", *a, *a) fmt.Printf("*b类型为 %T, 值为 %v \n", *b, *b) fmt.Println(s1.name, s1.age, s1.married, s1.sex) fmt.Println(a.name, a.age, a.married, a.sex) fmt.Println(s2.name, s2.age, s2.married, s2.sex) fmt.Println(b.name, b.age, b.married, b.sex) fmt.Println((*a).name, (*a).age, (*a).married, (*a).sex) fmt.Println((*b).name, (*b).age, (*b).married, (*b).sex) fmt.Printf("&a类型为 %T, 值为 %v \n", &a, &a) fmt.Printf("&b类型为 %T, 值为 %v \n", &b, &b) fmt.Println(&a.name, &a.age, &a.married, &a.sex) fmt.Println(&b.name, &b.age, &b.married, &b.sex) }运行结果如下:
s1类型为 main.Student, 值为 {Steven %!s(int=35) %!s(bool=true) %!s(int8=1)}
s2类型为 main.Student, 值为 {Sunny 20 false 0}
a类型为 *main.Student, 值为 &{Steven 35 true 1}
b类型为 *main.Student, 值为 &{Sunny 20 false 0}
*a类型为 main.Student, 值为 {Steven 35 true 1}
*b类型为 main.Student, 值为 {Sunny 20 false 0}
Steven 35 true 1
Steven 35 true 1
Sunny 20 false 0
Sunny 20 false 0
Steven 35 true 1
Sunny 20 false 0
&a类型为 **main.Student, 值为 0xc000006028
&b类型为 **main.Student, 值为 0xc000006030
0xc0000044a0 0xc0000044b0 0xc0000044b8 0xc0000044b9
0xc0000044c0 0xc0000044d0 0xc0000044d8 0xc0000044d9
2、空指针
在Go语言中,当一个指针被定义后没有分配到任何变量时,它的值为 nil。nil 指针也称为空指针。nil 在概念上和其他语言的 null、None、NULL 一样,都指代零值或空值。假设指针变量命名为 ptr。空指针判断如下。
if(ptr != nil) //ptr 不是空指针
if(ptr == nil) //ptr 是空指针
3、指针的使用
【示例】通过指针修改变量的数值package main import "fmt" func main(){ b := 3158 a := &b fmt.Println("b 的地址:", a) fmt.Println("*a 的值:", *a) *a++ fmt.Println("b 的新值:", b) }运行结果如下:
b 的地址: 0xc00000e0a8
*a 的值: 3158
b 的新值: 3159
package main import "fmt" func main(){ a := 58 fmt.Println("函数调用之前 a 的值:", a) fmt.Printf("%T \n", a) fmt.Printf("%x \n", &a) //b :=&a var b *int = &a change(b) fmt.Println("函数调用之后 a 的值:", a) } func change(val *int){ *val = 15 }运行结果如下:
函数调用之前 a 的值: 58
int
c00000e0a8
函数调用之后 a 的值: 15
声明:《Go系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。