Go 程式設計教學:結構 (Struct)

PUBLISHED ON SEP 19, 2017 — PROGRAMMING

    在先前的程式中,我們的變數都是儲存單一的值。如果想用變數表示較複雜的概念,像是在平面座標系中的某個點,先前的語法就不敷使用了。在 Go 語言,使用結構 (struct) 來表示複合的概念;此外,大部分的 Go 物件導向程式也會使用結構。本篇文章會介紹結構,但暫時不接觸物件導向的部分。

    Go 使用 struct 做為結構的關鍵字,這是承襲 C 的慣例。實例如下:

    package main
     
    import (
        "fmt"
    )
     
    type Point struct {
        x float64
        y float64
    }
     
    func main() {
        p := Point{x: 3.0, y: 4.0}
     
        fmt.Println(p.x)
        fmt.Println(p.y)
    }
    

    我們通常會在宣告結構時一併定義新的型別,便於後續程式呼叫,使用 type 可以宣告新型別。在本例中,我們宣告 Point 型別,該型別有兩個屬性 (field),分別是 xy,兩者皆是 float64 型別;接著,我們宣告一個變數 p 及賦值;最後,我們呼叫 p 的屬性 xy

    如果我們只需要使用結構,但不想創造新的型別,也可以使用匿名結構。實例如下:

    package main
     
    import (
        "fmt"
    )
     
    func main() {
        p := struct {
            x float64
            y float64
        }{x: 3.0, y: 4.0}
     
        fmt.Println(p.x)
        fmt.Println(p.y)
    }
    

    透過使用結構,我們可以比較有效率地處理數據。如下例:

    package main
     
    import (
        "fmt"
        "math"
    )
     
    type Point struct {
        x float64
        y float64
    }
     
    func main() {
        p := Point{x: 3.0, y: 4.0}
        q := Point{x: 0.0, y: 0.0}
     
        distance := math.Sqrt(math.Pow(p.x-q.x, 2) + math.Pow(p.y-q.y, 2))
        fmt.Println(distance)
    }
    

    結構的屬性,不一定要相同。見以下實例:

    package main
     
    import (
        "fmt"
    )
     
    type Gender int
     
    const (
        Male Gender = iota
        Female
    )
     
    type Person struct {
        name   string
        gender Gender
        age    uint
    }
     
    func main() {
        me := Person{gender: Male, age: 30, name: "Michael Chen"}
     
        fmt.Println(me.name)
        fmt.Println(me.age)
     
        if me.gender == Male {
            fmt.Println("Male")
        } else {
            fmt.Println("Female")
        }
    }
    

    在本程式中,我們先宣告新的型別 Gender,再定義相關的常數 MaleFemale;在這裡,我們使用 iota 自動產生常數。接著,宣告新的型別 Person,該型別有三個屬性,分別是 namegenderage,其中 gender 用到先前宣告的 Gender 型別。我們宣告新的變數 me並賦值,最後,將值印出;尤於 gender 內部是整數常數,無法印出,故自行轉為可識別的字串。

    結構內也可以再加入另一個結構,如下例:

    package main
     
    import (
        "fmt"
        "math"
    )
     
    type Point struct {
        x float64
        y float64
    }
     
    type Circle struct {
        r float64
        p Point
    }
     
    func main() {
        c := Circle{r: 5.0, p: Point{x: 3.0, y: 4.0}}
     
        fmt.Println(c.p.x)
        fmt.Println(c.p.y)
     
        circumstance := 2 * math.Pi * c.r
        fmt.Println(circumstance)
    }
    

    在本例中,結構 c 有兩個屬性,分別是半徑 r 和坐標 p,其中 p 本身又是由另一個結構組成。

    透過本例,各位讀者應該可以知道結構的基本使用方法。至於物件導向程式的部分,則待後續文章說明。在下一篇文章中,我們會介紹 Go 的內建容器 (collection):陣列 (array) 和切片 (slice)。