1. 程式人生 > >Go指針

Go指針

內容 變量賦值 判斷 指定 %d i++ 存儲 組元 run

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