Go指針
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
Go指針