Golang教程:指針


什么是指針

指針是存儲一個變量的內存地址的變量。 

 

在上圖中,變量 b 的值是 156,存儲在地址為 0x1040a124 的內存中。變量 a 存儲了變量 b 的地址。現在可以說 a 指向b

指針的聲明

一個指針變量指向了一個值的內存地址。

類似於變量和常量,在使用指針前你需要聲明指針。指針聲明格式如下:

var var_name *var-type

var-type 為指針類型,var_name 為指針變量名,* 號用於指定變量是作為一個指針。以下是有效的指針聲明:

var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮點型 */

讓我們寫一些代碼。

package main

import (  
    "fmt"
)

func main() {  
    b := 255
    var a *int = &b
    fmt.Printf("Type of a is %T\n", a)
    fmt.Println("address of b is", a)
}

& 操作符用來獲取一個變量的地址。在上面的程序中,第 9 行我們將 b 的地址賦給 aa 的類型為 *int)。現在我們說a 指向了 b。當我們打印 a 的值時,b 的地址將會被打印出來。程序的輸出為:

Type of a is *int  
address of b is 0x1040a124  

你可能得到的是一個不同的 b 的地址,因為 b 可以在內存中的任何地方

指針的空值

指針的空值為 nil 。

package main

import (  
    "fmt"
)

func main() {  
    a := 25
    var b *int
    if b == nil {
        fmt.Println("b is", b)
        b = &a
        fmt.Println("b after initialization is", b)
    }
}

在上面的程序中,b 的初始值為 nil。接着將 a 的地址賦值給 b。程序的輸出為:

b is <nil>  
b after initialisation is 0x1040a124  

指針解引用

解引用指針的意思是通過指針訪問被指向的值。指針 a 的解引用表示為:*a

讓我們通過一個程序看一下它是怎么工作的。

package main  
import (  
    "fmt"
)

func main() {  
    b := 255
    a := &b
    fmt.Println("address of b is", a)
    fmt.Println("value of b is", *a)
}

上面程序的第10行,我們將 a 解引用並打印這個解引用得到的值。和我們預期的一樣,程序打印的是 b 的值。程序的輸出為:

address of b is 0x1040a124  
value of b is 255  

讓我們再寫一個程序,該程序使用指針改變 b 的值。

package main

import (  
    "fmt"
)

func main() {  
    b := 255
    a := &b
    fmt.Println("address of b is", a)
    fmt.Println("value of b is", *a)
    *a++
    fmt.Println("new value of b is", b)
}

在上面的程序中,我們將 a 指向的值自增 1,這樣做也改變了 b 的值,因為 a 指向 b。因此 b 的值變為 256。程序的輸出為:

address of b is 0x1040a124  
value of b is 255  
new value of b is 256  

傳遞指針給函數

package main

import (  
    "fmt"
)

func change(val *int) {  
    *val = 55
}
func main() {  
    a := 58
    fmt.Println("value of a before function call is",a)
    b := &a
    change(b)
    fmt.Println("value of a after function call is", a)
}

在上面的程序中,第 14 行,我們將指向 a 的指針 b 傳遞給函數 change。在函數 change 內部,第 8 行,通過解引用修改了 a 的值。程序的輸出如下:

value of a before function call is 58  
value of a after function call is 55

不要傳遞指向數組的指針給函數,而是使用切片

假設我們需要通過函數修改一個數組。一個辦法是將數組的指針作為參數傳遞給函數。

package main

import (  
    "fmt"
)

func modify(arr *[3]int) {  
    (*arr)[0] = 90
}

func main() {  
    a := [3]int{89, 90, 91}
    modify(&a)
    fmt.Println(a)
}

在上面的程序中,第13行,數組 a 的地址傳遞給了函數 modify。在第8行的 modify 函數中,我們通過解引用的方式將數組的第一個元素賦值為 90。程序輸出為:[90 90 91]

a[x] 是 (*a)[x] 的簡寫,因此上面的程序中,(*arr)[0] 可以替換為 arr[0]。讓我們用這種簡寫方式重寫上面的程序:

package main

import (  
    "fmt"
)

func modify(arr *[3]int) {  
    arr[0] = 90
}

func main() {  
    a := [3]int{89, 90, 91}
    modify(&a)
    fmt.Println(a)
}

程序的輸出依然是:[90 90 91]

雖然可以通過傳遞數組指針給函數的方式來修改原始數組的值,但這在 Go 中不是慣用的方式,我們可以使用切片完成同樣的事情。

讓我們用切片的方式重寫上面的程序:

package main

import (  
    "fmt"
)

func modify(sls []int) {  
    sls[0] = 90
}

func main() {  
    a := [3]int{89, 90, 91}
    modify(a[:])
    fmt.Println(a)
}

在上面的程序中,第13行,我們傳遞了一個切片給 modify 函數。在函數內部,切片的第一個元素被修改為 90。程序的輸出為:[90 90 91]。所以請不要以數組指針作為參數傳遞給函數,而是使用切片:)。這樣的代碼更加簡潔,在 Go 中更常被使用。

Go 不支持指針運算

Go 不支持其他語言(比如C)中的指針運算。

package main

func main() {  
    b := [...]int{109, 110, 111}
    p := &b
    p++
}

上面的程序將報錯:main.go:6: invalid operation: p++ (non-numeric type *[3]int)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM