struct概述
結構體是go語言最重要的數據結構之一,go和其它編程語言不一樣,它沒有類的概念,類比過來struct就相當于其它語言中的類,因此十分重要。
結構體這部分涉及到的知識點頁比較多,此文偏長,請耐心閱讀。
1. 認識結構體
直接說語法往往非??菰?,在正式開始前,我們先來看一段簡單的結構體代碼,建立整體感知,后續我們再一一細說其中的知識點。
package main import "fmt" type Person struct { Name string Age int8 } func (p Person) GetName() { fmt.Printf("My name: %s ", p.Name) } func main() { p := Person{ Name: "zhangsan", Age: 18, } p.GetName() }
看到了吧,還是很簡單的,跟著注釋你大概已經看懂了如何使用。下面我們拆分成知識點細細分析
1.1 如何定義
它按照如下方式定義(PS: 它還可以代標簽,為簡單起見,這里暫且不討論)
type 結構體名 struct {
字段名1 字段類型1
字段名2 字段類型2
.....
}
1.2 實例化
主要有幾種方式:
var p = new(Person)
var p Person
var p = Person{}
p := Person{
Name: "zhangsan",
Age: 18,
}
p := Person{"zhangsan", 18}
實際例化后我們可以通過obj.字段名的方式調出值,如上例中p.Name
1.3 方法
結構體方法,對應到面向對象語言中就是實例方法.
在上例中,如下部分:
func (p Person) GetName() {
fmt.Printf("My name: %s
", p.Name)
}
方法和函數有什么主要區別呢?
方法它有接收者,而函數沒有
1.4 接收者
接收者既可以是值也可以是指針類型,我們看下:
package main
import "fmt"
type Person struct {
Name string
Age int8
}
func (p Person) GetName() {
fmt.Printf("My name: %s
", p.Name)
}
func (p *Person) GetAge() {
fmt.Printf("My age: %d
", p.Age)
}
func main() {
p1 := Person{Name: "張三", Age: 18}
p2 := &Person{Name: "李四", Age: 16}
p1.GetName()
p1.GetAge()
fmt.Println("---------分割線-------")
p2.GetName()
p2.GetAge()
}
我們可以發現,無論接收者是值類型還是指針類型,它們在調用上卻不會有任何區別,這是因為go編譯器會悄悄自動幫我轉換, nice!
1.5 指針接收者or值接收者
那么什么時候使用值接收者啥時候用指針接收者呢?
在go中一般約定,同一個struct接收者類型保持一致(要么全是指針接收者,要么全是值接收者)
值接收者:結構體相對較小(拷貝成本不高),不需要改變結構體內部值場景
指針接收者:結構體比較大(拷貝成本高),需要改變結構體內部值場景
2. 匿名字段及嵌套
匿名字段可以說是結構體最有用的功能,使用的地方比比皆是,下面我們來看下
2.1 匿名字段
所謂匿名字段指的是在結構體中字段名可以不用顯示寫出來,比如:
package main
import "fmt"
type Data struct {
uint8
}
func main() {
d := Data{8}
fmt.Println(d.uint8)
}
關鍵點在于字段名 == 類型名
2.2 結構體嵌套
在開始之前我們來看下兩個結構體
type Person struct {
Name string
Age int8
}
type Student struct {
ID int
Name string
Age int8
Score float32
}
我們會發現學生結構體和人結構體相比只多了兩個字段(ID和Score)分別定義有點浪費?另外人和學生有許多相似的地方,某些時候Person結構體中的方法,Student同樣也需要,如果分別寫兩份相同的方法,也很浪費?
好啦!在go中可以通過嵌套解決,直接看代碼
package main
import "fmt"
type Person struct {
Name string
Age int8
}
func (p Person) GetName() {
fmt.Printf("My name: %s
", p.Name)
}
type Student struct {
ID int
Score float32
Person
}
func (s Student) GetScore() {
fmt.Printf("My score: %v
", s.Score)
}
func main() {
p := Student{
ID: 1,
Score: 98,
Person: Person{
Name: "zhangsan",
Age: 18,
},
}
fmt.Printf("My age: %d
", p.Age)
fmt.Printf("My age p.Person.age: %d
", p.Person.Age)
p.GetScore()
p.GetName()
p.Person.GetName()
}
上面的注釋已經非常詳細,這里總結下規律:
匿名結構體嵌套,會有如下效果:
匿名結構體中字段,當前結構體可以直接調用
匿名結構體方法,當前結構體可以直接調用
本質是:go在字段查找時,現在本結構體中找,如果找不到則到匿名結構體中查找;方法同理
2.3 匿名結構體嵌套經典使用
數據庫表設計中: 我們可以把常用的字段抽出來成一個結構體,其它結構體只需要引入就可以擴展其中字段以及方法,比如:
package main import ( "fmt" "time" ) type BaseTable struct { ID int CreatedAt time.Time UpdatedAt time.Time } type User struct { Name string BaseTable }
3. 方法值和方法表達式
方法值和方法表達式類似于函數表達式,我們可以將函數表達式當作變量傳遞,方法值和方法表達式也是一樣,文字上不太容易明白,直接看代碼
package main
import (
"fmt"
)
type Person struct {
Name string
Age int8
}
func (p Person) GetName() {
fmt.Printf("My name: %s
", p.Name)
}
func main() {
p := Person{Name: "zhangsan", Age: 18}
getName := p.GetName
getName()
fmt.Println("--------分割線-------")
pGetName := Person.GetName
pGetName(p)
}
它可以做為變量取出,因此可以實現復雜精巧場景下的使用,舉例這里不做舉例,方法值和方法表達式的區別在于:
方法表達式需要把接收者做為參數傳入
審核編輯:黃飛
-
指針
+關注
關注
1文章
484瀏覽量
71843 -
編譯器
+關注
關注
1文章
1672瀏覽量
51592 -
數據結構
+關注
關注
3文章
573瀏覽量
41584 -
面向對象
+關注
關注
0文章
64瀏覽量
10251 -
Struct
+關注
關注
0文章
31瀏覽量
11266
原文標題:golang結構體看這篇就夠啦
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
Golang接口的作用和應用場景
一個經典的結構體和聯合體共用的實例
漫談C語言結構體
請問怎么在樹莓派上從源代碼構建Golang?
串口傳輸結構體是什么意思
利用golang優雅的實現單實例分享
golang的調度模型-GPM 模型的源碼結構
golang orm庫xorm的使用和項目結構
golang結構體實例代碼
評論