結構體就是一個復雜的數據類型,里面可以包含字段,也可以嵌套其他結構體
Go 中沒有 class,可以使用 struct 代替
聲明
通過 type she
type struct_name struct {
field_name1 field_type1
field_name2 field_type2
}
示例:
type student struct {
Name string
Age int
score int
}
實例化
結構體有 3 種實例化方式
// 直接初始化
var stu student
// 通過 new 進行初始化
var stu *student = new(student)
stu := new(student)
// 賦值初始化
stu := student{}
// 等效於 stu := new(student)
var stu *student = &student{}
stu := &student{}
訪問
通過 . 可以訪問到結構體內的字段
指向結構體的指針也可以直接訪問
(*struct_name).field_name == struct_name.field_name
儲存結構
結構體內部儲存的數據在內存中都是連續的
tag
由於 Go 中限制只有以大寫字母開頭的才能在其他包中訪問到
可以通過 tag 使得指定包中獲取到的名稱
示例:
// 小寫字母開頭的無法在其他包中訪問
type student1 struct {
Name string
Age int
score int
}
// 設置 tag 使得 json 包中訪問數據可以自定義
type student2 struct {
Name string `json:"name"`
Age int `json:"age"`
Score int `json:"score"`
}
func jsonTest() {
stu1 := student1{
Name: "Tom",
Age: 18,
score: 90,
}
stu2 := student2{
Name: "Tom",
Age: 18,
Score: 90,
}
res, err := json.Marshal(stu1)
if err != nil {
fmt.Printf("some error occured: %v", err)
} else {
fmt.Printf("student1: %s\n", string(res))
}
res, err = json.Marshal(stu2)
if err != nil {
fmt.Printf("some error occured: %v", err)
} else {
fmt.Printf("student2: %s\n", string(res))
}
}
輸出結果:
student1: {"Name":"Tom","Age":18}
student2: {"name":"Tom","age":18,"score":90}
匿名字段
定義結構體時,可以省略字段名只寫類型,這樣就定義了一個匿名字段
由於結構體中字段名必須時唯一的,所以匿名的類型也必須是唯一的
示例:
type foo struct {
field1 int
string
}
func main() {
bar := foo{}
bar.field1 = 1
bar.string = "hello world"
fmt.Printf("%v", bar)
}
結構體嵌套
在結構體中嵌套結構體時使用匿名字段可以更加簡便獲取內層結構體的字段
當 內層結構體的字段 和 外層結構體的字段 沒有重復時可以直接獲取,如果有重復時需要加上 內層結構體名 才能正常獲取
這就是 Go 實現繼承的方式
匿名字段訪問示例:
type foo struct {
field1 int
field2 string
}
type bar struct {
foo
field1 string
field3 int
}
func main() {
foobar := bar{}
foobar.foo.field1 = 1
foobar.field2 = "hello"
foobar.field1 = "world"
foobar.field3 = 2
fmt.Printf("%v", foobar)
}
輸出結果:
{{1 hello} world 2}
如果沒有使用匿名字段,這時就是組合,即使 內層結構體的字段 和 外層結構體的字段 沒有重復時也不能省略結構體名
組合
組合和嵌套匿名結構體相似,但是結構體名稱不能省略
