Go 语言指针
Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务。
接下来让我们来一步步学习 Go 语言指针。
我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。
Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。
以下实例演示了变量在内存中地址:
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main(){ 8 var name string 9 name = "demon" 10 fmt.Println("name变量的指针地址:",&name) 11 }
以上代码运行返回的结果:
name变量的指针地址: 0xc420076050
什么是指针
一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。
类似于变量和常量,在使用指针前你需要声明指针。指针声明格式如下:
var var_name(变量名) *var_name_type(数据类型)
var_name就是变量的名称,var_name_type是指针的数据类型,*用于指定变量是一个指针,例如以下的指针声明
var name *string //指向字符串类型的指针 var age *int //指向整数型类型的指针
如何使用指针
指针使用流程:
- 定义指针变量。
- 为指针变量赋值。
- 访问指针变量中指向地址的值。
在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 8 func main(){ 9 //定义局部变量num1 num2 10 var num1 int = 50 11 var num2 *int 12 13 //获取num1变量的内存地址并赋值给num2变量 14 num2 = &num1 15 16 fmt.Println("num1变量的内存地址为:", &num1) 17 fmt.Println("num2变量指针的地址为:", num2) 18 19 //获取变量num1的值 20 fmt.Println("num1变量的值为:", num1) 21 //获取变量num2的值 22 fmt.Println("num2变量的值为:", *num2) 23 24 }
以上代码返回的运行结果:
num1变量的内存地址为: 0xc42006e178 num2变量指针的地址为: 0xc42006e178 num1变量的值为: 50 num2变量的值为: 50
Go 空指针
当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。
一个指针变量通常缩写为 ptr。
查看以下实例:
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main(){ 8 //初始化局部变量 ptr s 分别都是空指针 9 var ptr *int 10 var s *string 11 //初始化局部变量num1 num2,因为num1赋值了并且num2的指针指向了num1 12 var num1 float32 = 50.123 13 var num2 *float32 14 num2 = &num1 15 16 //分别输出变量的值 17 fmt.Printf("ptr的空指针的值为:%v\n", ptr) 18 fmt.Printf("s的空指针的值为:%v\n", s) 19 fmt.Printf("num2的值为%v\n", *num2) 20 21 //做判断,如果是空指针的话值就是nil 22 if ptr == nil{ 23 fmt.Println("ptr是空指针哦~") 24 } 25 26 if s == nil{ 27 fmt.Println("s是空指针哦~") 28 } 29 30 if num2 == nil{ 31 fmt.Println("num2的是空指针哦~") 32 }else { 33 fmt.Println("num2的值为:", *num2) 34 } 35 36 }
以上代码返回的运行结果:
ptr的空指针的值为:<nil> s的空指针的值为:<nil> num2的值为50.123 ptr是空指针哦~ s是空指针哦~ num2的值为: 50.123
Go 语言指针数组
number为整型指针数组。因此每个元素都指向了一个值。以下实例的三个整数将存储在指针数组中:
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main(){ 8 //定义一个blance数组,并且拥有五个元素 9 var blance = [5] int {1,2,3,4,5} 10 //定义常量MAX为5 11 const MAX int = 5 12 //定义数组指针number 13 var number [MAX] *int 14 15 for i := 0; i< MAX; i++{ 16 //分别给number的数组中的每个索引赋值,值是引用blance数组中的每个元素的内存地址 17 number[i] = &blance[i] 18 fmt.Printf("blance[%d] = %d \n", i, blance[i]) 19 } 20 21 fmt.Println("----------------------") 22 23 for i := 0; i< MAX; i++{ 24 fmt.Printf("number[%d] = %d \n", i, *number[i]) 25 } 26 27 fmt.Println("----------------------") 28 29 for i := 0; i< MAX; i++{ 30 //如果blance数组与number数组一样,并且里面只的内存地址都一样,则打印两个数组元素的内存地址 31 if blance[i] == *number[i] && &blance[i] == number[i]{ 32 fmt.Printf("blance[%d] %v number[%d] %v \n",i , &blance[i], i ,number[i]) 33 34 } 35 } 36 }
以上代码返回的运行结果:
blance[0] = 1 blance[1] = 2 blance[2] = 3 blance[3] = 4 blance[4] = 5 ---------------------- number[0] = 1 number[1] = 2 number[2] = 3 number[3] = 4 number[4] = 5 ---------------------- blance[0] 0xc4200141e0 number[0] 0xc4200141e0 blance[1] 0xc4200141e8 number[1] 0xc4200141e8 blance[2] 0xc4200141f0 number[2] 0xc4200141f0 blance[3] 0xc4200141f8 number[3] 0xc4200141f8 blance[4] 0xc420014200 number[4] 0xc420014200
来来来来,用Python来嘲讽一波golang的数组引用赋值~
1 #!/usr/bin/env python3 2 # _*_coding:utf-8_*_ 3 4 __author__ = ‘demon‘ 5 6 #声明列表l1 7 l1 = [‘demon‘,‘18‘,‘beijing‘,"python","golang","linux"] 8 #浅拷贝列表l1中的每个元素 9 l2 = l1[:] 10 11 l1_len = len(l1) 12 13 for i in range(l1_len): 14 #判断列表中每个元素的内存地址是否一致 15 if id(l1[i]) == id(l2[i]): 16 #打印两个列表中给的每个元素及内存地址 17 print("l1[{}] {:10} l2[{}] {:10} at {memory}".format(i,l1[i],i,l2[i],memory=id(l1[i])))
以上代码返回的运行结果:
l1[0] demon l2[0] demon at 4302152624 l1[1] 18 l2[1] 18 at 4330894536 l1[2] beijing l2[2] beijing at 4330894200 l1[3] python l2[3] python at 4329981408 l1[4] golang l2[4] golang at 4330894984 l1[5] linux l2[5] linux at 4329974728
Go 语言指向指针的指针
如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。
当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址:
指向指针的指针变量声明格式如下:
var ptr **int;
以上指向指针的指针变量为整型。
访问指向指针的指针变量值需要使用两个 * 号,如下所示:
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 9 var a int 10 var ptr *int 11 var pptr **int 12 13 a = 3000 14 15 //指针ptr地址 16 ptr = &a 17 18 //指向指针ptr地址 19 pptr = &ptr 20 21 //*获取pptr的值 22 fmt.Printf("变量 a = %d\n", a ) 23 fmt.Printf("指针变量 *ptr = %d\n", *ptr ) 24 fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr) 25 }
以上代码返回的运行结果:
变量 a = 3000 指针变量 *ptr = 3000 指向指针的指针变量 **pptr = 3000
Go 语言指针作为函数参数
Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可。
以下实例演示了如何向函数传递指针,并在函数调用后修改函数内的值:
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 //可以接收指针作为参数的自定义函数 8 func person(name *string,age *int) string { 9 //修改指针指向的name变量的值,影响了name的值 10 *name = "大佬" 11 fmt.Println("person函数内部的name的内存地址:", name) 12 fmt.Printf("person函数内部的修改后name变量值:%s", *name) 13 return "" 14 15 } 16 17 func swap(x ,y int) string{ 18 //修改x,y的值,x,y作为局部变量传递进来,因为没有使用指针,所以不会影响函数外部的x,y变量值 19 x, y = 50,100 20 fmt.Println("swap函数内部的x变量值:", x) 21 fmt.Println("swap函数内部的y变量值:", y) 22 return "" 23 } 24 25 func main() { 26 //初始化局部变量 27 var name string = "demon" 28 var age int = 18 29 var x int = 10 30 var y int = 20 31 32 fmt.Println("person函数内部的修改后name变量值:", name) 33 fmt.Println("person函数外部的name的内存地址:", &name) 34 fmt.Println(person(&name, &age)) 35 fmt.Printf("person函数外部的修改后name变量值:%s \n",name) 36 37 fmt.Println("--------------------------------------------") 38 fmt.Println(swap(x,y )) 39 fmt.Println("swap函数外部的x变量值:", x) 40 fmt.Println("swap函数外部的y变量值:", y) 41 42 }
以上代码返回的运行结果:
person函数内部的修改后name变量值: demon person函数外部的name的内存地址: 0xc42006e1a0 person函数内部的name的内存地址: 0xc42006e1a0 person函数内部的修改后name变量值:大佬 person函数外部的修改后name变量值:大佬 -------------------------------------------- swap函数内部的x变量值: 50 swap函数内部的y变量值: 100 swap函数外部的x变量值: 10 swap函数外部的y变量值: 20