位元詩人 [Golang] 程式設計教學:使用指標 (Pointer)

Golang指標
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

如同其他的編譯語言 (compiled language),Go 支援指標 (pointer)。在 C/C++ 中,指標是必經的門檻;但指標對初學者來說不是很好懂,時常會因誤用指標而造成 segment fault 等錯誤,許多程式學習者對指標有不好的回憶。不過,在 Go 裡面,指標比較簡化,不僅沒有指標運算,也不需要手動控制記憶體釋放。

建立指標

指標本身存的值是指向另一個值的記憶體位置 (memory address),我們通常不會直接使用指標的值,而會透過指標間接操作另一個值。在以下實例中,我們建立一個指向整數的指標:

package main

import (
    "fmt"
    "log"
)

func main() {
    n := 2

    // Reference the adress from the variable.
    nPtr := &n

    // Print out the address.
    fmt.Println(nPtr)

    // Dereference the pointer to get the value.
    if !(*nPtr == 2) {
        log.Fatal("Wrong value")
    }
}

動態配置記憶體

我們也可以動態配置記憶體,見下例:

package main

import (
    "fmt"
    "log"
)

func main() {
    // Allocate a chunk of memory.
    nPtr := new(int)

    // Assign the value indirectly.
    *nPtr = 2

    // Print out the address.
    fmt.Println(nPtr)

    // Dereference the pointer to get the value.
    if !(*nPtr == 2) {
        log.Fatal("Wrong value")
    }
}

實際上,我們比較少對基礎型別進行動態記憶體分配,但我們可以對結構等複合型別動態配置記憶體,如下例:

package main

import (
    "fmt"
)

type Point struct {
    x float64
    y float64
}

func main() {
    p := new(Point)

    p.x = 3.0
    p.y = 4.0

    fmt.Println(fmt.Sprintf("(%.2f, %.2f)", p.x, p.y))
}

對結構動態分配記憶體相當有用,Go 物件導向程式大量使用這種語法。

我們前述的 make 函式其實也是動態分配記憶體的一種語法,但 make 回傳的不是指標,而是該型別本身;因此,我們不需要使用指標的語法操作陣列、切片和 map,這是 Go 簡化語法的一種方式。

結語

在 Go 裡面,指標除了用來和 C 函式庫互動外,當變數較大時,傳遞指標較傳遞整個變數有效率得多,日後談到函式和物件時都會用到指標。由於 Go 不需手動管理記憶體,也沒有指標運算,Go 指標較 C 指標簡化許多。

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。