Hike News
Hike News

Golang物件導向初識-day16-結構體方法1

定義類型的別名

  1. 結構體是用戶單獨定義的類型,不能和其他Go內置類型進行強制轉換(如int,string等)
  2. 類型仍可透過type重新命名(別名),但是與原類型為不同類型
    1
    2
    3
    4
    type 原類型 類型別名

    type integer int
    type stu Student
  • 在定義struct的別名時,即使內部的字段(屬性)都相同,別名類型與原類型仍為不同類型
  • 因此不同類型之間不能賦值也不能運算
  • 若要是進行賦值及運算則必須強制轉換

工廠模式(構造函數)

構造函數:對象不需要參數即可調用的構造函數。對象生成時如果沒有顯式地調用構造函數,則預設構造函數會被自動調用。
可是在Golang中,並無構造函數存在因此需顯式的使用工廠模式調用自定義的構造函數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package model

type student struct {
Name string
Age int
Score float32
}

func NewStudent(Name string, Age int, Score float32)*student{
var New *student = &student{
Name : Name,
Age : Age,
Score : Score,
}
return New
}

//於main包調用model包中的自定義構造函數
package main

func main(){
Tom := model.NewStudent("Tom",18,90)
}

struct中的tag

  • tag 相當於struct中字段的原信息
  • 我們可以為struct中的每個字段,在字段的類型後面寫上一個tag
  • tag相當於這個字段的說明,編譯器會將tag儲存,並作為此字段的描述
  • 這個tag可通過反射的機制獲取到
  • 最常用的場景就是json的序列化反序列化
  • 通常json打包所使用的大部分都是小寫字母,但Go語言在包外要引用結構體內的字段需要首字大寫才能訪問,使用tag指定字段來調用struct

聲明tag

1
2
3
4
type Student struct {
name string `NameFieldTag`
age int `AgeFieldTag`
}

json序列化與反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"encoding/json"
"fmt"
)

//透過tag反射找到字段
type Student struct{
Name string `json:"name"`
Age int `json:"age"`
}

func main(){
var stu = Student{
Name : "Tom",
Age : 18,
}

//使用json package序列化 其返回的是字符數組( []bytes )
data ,err := json.Marshal(stu)

if err != nil {
fmt.Println("json encoding failed:",err)
return
}

//將打包完的訊息從[]bytes轉成string
fmt.Println(string(data))
}

result

1
{"name":"Tom","age":18}
  • 從結果可得知,我們所使用的json tag為小寫,透過外部的json package訪問到被打包的字段便是小寫的
  • 亦剛好符合json大部分皆為小寫的需求
  • 透過json key取得其對應的value

匿名字段

結構體中的可以包含字段是只有類型,沒有名字,即匿名字段

example

1
2
3
4
5
6
7
8
9
10
11
12
//定義結構體
type Car struct{
Name string
Age int
}

//於另一個結構體中包含Car結構體類型的數據,但不聲明字段
type Train struct{
Car //匿名字段
Start time.Time
int //匿名字段
}

訪問

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main

import (
"fmt"
"time"
)

type car struct {
Name string
Age int
}

type Train struct {
car
start time.Time
int
Age int
}

func main(){
//定義TzeChiang變量為Train類型
var TzeChiang Train

//如匿名字段為結構體類型,且結構體中的字段唯一,可直接使用 實例化對象.字段訪問
TzeChiang.Name = "TzeChiang"

//若不唯一,或是優先級次於原類型其他字段,可使用實例化對象.結構體類型.字段訪問
TzeChiang.car.Age = 30

//其他匿名字段亦可實例化對象.字段訪問
TzeChiang.int = 8757

fmt.Println(TzeChiang)
}

result

1
{{TzeChiang 30} {0 0 <nil>} 8757}