在先前的程式中,我們的變數都是儲存單一的值。如果想用變數表示較複雜的概念,像是在平面座標系中的某個點,先前的語法就不敷使用了。在 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),分別是 x
和 y
,兩者皆是 float64
型別;接著,我們宣告一個變數 p
及賦值;最後,我們呼叫 p
的屬性 x
和 y
。
如果我們只需要使用結構,但不想創造新的型別,也可以使用匿名結構。實例如下:
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: Female, age: 30, name: "Michelle Chen"}
fmt.Println(me.name)
fmt.Println(me.age)
if me.gender == Male {
fmt.Println("Male")
} else {
fmt.Println("Female")
}
}
在本程式中,我們先宣告新的型別 Gender
,再定義相關的常數 Male
和 Female
;在這裡,我們使用 iota
自動產生常數。接著,宣告新的型別 Person
,該型別有三個屬性,分別是 name
、 gender
、age
,其中 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)。