golang_結構體初窺
在golang中並沒有類(class)的概念,但是使用struct可以達到更高的靈活度--但是golang中的結構體與C/C++中的結構體有所不同,你將會在接下來的內容中看見.
知識點:
結構體的定義:
type person struct {
name string
age uint8
sex string
}
結構體實例化(定義結構體類型的變量)
p1 := person{
name: "stocking",
age: 18,
sex: "angle",
}
var p2 person
p2 = person{
name: "panty",
age: 19,
}
p3 := person{
"Garterbelt",
44,
"gay",
}
注意:
1. 在定義的時候字段之間不需要使用分隔符,但是在初始化的時候需要,即使是最後一個字段
2. 在初始化的時候使用的是冒號`:`而不是等號
3. 初始化的時候字段順序可以不按照定義時候的順序,但是名字必須是結構體中存在的
4. 不是每一個字段都需要初始化
5. 初始化的時候可以省略字段的名字,但是你的值得按照定義時候的順序給--類型必須對應
訪問結構體的成員變量(字段)
var name string = p1.name
var age uint = p2.age
var sex string = p3.sex
fmt.Println(name, age, sex)
只需要使用變量.字段
即可訪問對應的字段
匿名結構體: 與匿名函數相似,就是一個沒有名字的結構體,一般用於存儲臨時數據
var dog struct {
name string
japaneseName string
}
dog.name = "Chuck"
dog.japaneseName = "チャック"
知識點++:
指針結構體:
p1 := new(person)
p1.name = "stocking"
p1.age = 18
p1.sex = "angle"
p2 := &person{
name: "panty",
age: 19,
sex: "angle",
}
p1是直接使用new()
函數來完成的,而p2是通過對指針取地址,但是他們的效果都是一樣的=>使用結構體的地址來賦值給變量和直接使用new是一樣的.
構造函數
構造函數就是專門用於初始化結構體的函數--在其他語言中構造函數是類的初始化函數,但是由於golang沒有類,所以構造函數無法在創建結構體變量的時候自動調用(雖然系統也會將其自動初始化,但是只會初始化為默認值).
func newPerson(name string, age uint, sex string) *person {
return &person{
name: name,
age: age,
sex: sex,
}
}
func main() {
stocking := newPerson("stocking", 18, "angle")
fmt.Println(stocking)
}
在編寫構造函數的時候,一般使用new+結構體名字
作為函數的命名,這是一種約定俗成,雖然不是強制要求,但是可以看做一種規範.但是你仔細看就會發現,其實所謂的構造函數就是返回一個結構體指針,並且賦值給一個變量.
方法
前面我們已經多次提及,在golang中沒有class的概念,那麼方法的作用對象自然也就便成了結構體.
func introtion(p person) {
fmt.Printf("I'm %s , %d ages %s", p.name, p.age, p.sex)
}
func main() {
p1 := newPerson("stocking", 18, "angle")
introtion(*p1)
}
這裡我們不難發現,這其實與普通的方法沒什麼不同,只要傳入一個對應的類型就行了.那麼,怎麼樣才能讓他像其他語言一樣只有"對象"才能調用方法呢?同時我們發現當我們使用構造函數創建對象的時候在參數傳遞的時候還需要傳遞一個*p
這就是我們馬上就要說到的 -- 接收者.
接收者:
為了讓方法只作用於特定的結構體而出現的一個東西.其實很簡單的一個概念,我們直接看示例:
func (p person) say() {
fmt.Printf("%s say hi!!!", p.name)
}
func main() {
p1 := newPerson("stocking", 18, "angle")
p1.say()
}
在方法定義的時候在前面使用一個括號包括一個結構體名字和參數即可.這就相當於C++中的this
關鍵字,只不過C++的方法是屬於類裡面,所以不需要特殊說明.
調用方式是不是簡單了很多?而且如果你使用的編輯器有代碼提示功能,你就會發現當你輸入p1.
的時候後面自然就會出現該方法名(下圖是在vscode中的效果).
在方法中還有一點需要注意: 你是否需要改變調用對象,如果你需要改變調用對象的內容那麼在方法定義的時候前面的接收者要使用指針類型,如果不需要改變調用對象,那麼方法定義的時候使用普通接收者即可
匿名字段:
結構體中的字段可以沒有名字,只有類型,在這個時候調用 的時候只需要使用其類型名即可,同樣因為這一點,所以同一個結構體當中同一個類型的匿名字段只能有一個.
6. 結構體嵌套:
結構體可以嵌套另一個結構體,
type person struct {
name string
age uint
}
type angle struct {
person
string
}
func main() {
var a = angle{
person{
"stocking",
18,
},
"cake",
}
fmt.Println(a.string) // 輸出cake
}
如果被嵌套的結構體和外部的結構體中包含相同的字段,那麼只需要使用結構體名字就能區分.