結構體的定義只是一種內存布局的描述,只有當結構體實例化時,才會真正地分配內存。因此必須在定義結構體並實例化后才能使用結構體的字段。
實例化就是根據結構體定義的格式創建一份與格式一致的內存區域,結構體實例與實例間的內存是完全獨立的。
Go語言可以通過多種方式實例化結構體,根據實際需要可以選用不同的寫法。
基本的實例化形式
結構體本身是一種類型,可以像整型、字符串等類型一樣,以 var 的方式聲明結構體即可完成實例化。
基本實例化格式如下:
var ins T
其中,T 為結構體類型,ins 為結構體的實例。
用結構體表示的點結構(Point)的實例化過程請參見下面的代碼:
純文本復制
type Point struct {
X int
Y int
}
var p Point
p.X = 10
p.Y = 20
在例子中,使用.來訪問結構體的成員變量,如 p.X 和 p.Y 等。結構體成員變量的賦值方法與普通變量一致。
創建指針類型的結構體
Go語言中,還可以使用 new 關鍵字對類型(包括結構體、整型、浮點數、字符串等)進行實例化,結構體在實例化后會形成指針類型的結構體。
使用 new 的格式如下:
ins := new(T)
其中:
T 為類型,可以是結構體、整型、字符串等。
ins:T 類型被實例化后保存到 ins 變量中,ins 的類型為 *T,屬於指針。
Go語言讓我們可以像訪問普通結構體一樣使用.訪問結構體指針的成員。
下面的例子定義了一個玩家(Player)的結構,玩家擁有名字、生命值和魔法值,實例化玩家(Player)結構體后,可對成員進行賦值,代碼如下:
type Player struct{
Name string
HealthPoint int
MagicPoint int
}
tank := new(Player)
tank.Name = "Canon"
tank.HealthPoint = 300
經過 new 實例化的結構體實例在成員賦值上與基本實例化的寫法一致。
Go語言和C/C++
在 C/C++ 語言中,使用 new 實例化類型后,訪問其成員變量時必須使用->操作符。
在 Go語言中,訪問結構體指針的成員變量時可以繼續使用.。這是因為 Go語言為了方便開發者訪問結構體指針的成員變量,使用了語法糖(Syntactic sugar)技術,將 ins.Name 形式轉換為 (*ins).Name。
取結構體的地址實例化
在 Go語言中,對結構體進行&取地址操作時,視為對該類型進行一次 new 的實例化操作。取地址格式如下:
ins := &T{}
其中:
T 表示結構體類型。
ins 為結構體的實例,類型為 *T,是指針類型。
下面使用結構體定義一個命令行指令(Command),指令中包含名稱、變量關聯和注釋等。對 Command 進行指針地址的實例化,並完成賦值過程,代碼如下:
type Command struct {
Name string // 指令名稱
Var *int // 指令綁定的變量
Comment string // 指令的注釋
}
var version int = 1
cmd := &Command{}
cmd.Name = "version"
cmd.Var = &version
cmd.Comment = "show version"
代碼說明如下:
第 1 行,定義 Command 結構體,表示命令行指令
第 3 行,命令綁定的變量,使用整型指針綁定一個指針。指令的值可以與綁定的值隨時保持同步。
第 7 行,命令綁定的目標整型變量:版本號。
第 9 行,對結構體取地址實例化。
第 10~12 行,初始化成員字段。
取地址實例化是最廣泛的一種結構體實例化方式。可以使用函數封裝上面的初始化過程,代碼如下:
純文本復制
func newCommand(name string, varref *int, comment string) *Command {
return &Command{
Name: name,
Var: varref,
Comment: comment,
}
}
cmd = newCommand(
"version",
&version,
"show version",
)