[Golang] Struct
此篇為各筆記之整理,非原創內容,資料來源可見下方連結與文後參考資料: 👍 Structures in Go (structs) @ medium > rungo
TL;DR
// create struct on the fly
foo := struct {
Hello string
}{
Hello: "World",
}
Anonymous Field:
Promoted Field
type User struct {
firstName string
lastName string
birthDate string
createdAt time.Time
}
type Admin struct {
email string
password string
// anonymous / embedded field:直接帶入 User 裡面有的欄位
User
}
func main() {
a := Admin{}
a.firstName = "Aaron"
a.lastName = "Chen"
// 使用 anonymous/embedded field 可以直接取得該 nested struct 的值
// 這個行為稱作 Promoted
fmt.Println(a.firstName, a.lastName)
}
三種宣告 Person struct 的方式:
- 使用 new syntax:第二種和第三種寫法是一樣的
var user1 *Person // nil
user2 := &Person{} // {},user2.firstName 會是 ""
user3 := new(Person) // {},user3.firstName 會是 ""
structs 是在 GO 中的一種資料型態,它就類似 JavaScript 中的物件(Object)或是 Ruby 中的 Hash。
定義與使用基本的 struct
建立一個 person 型別,它本質上是 struct:
// STEP 1:建立一個 person 型別,它本質上是 struct
type Person struct {
firstName string
lastName string
}
// 等同於
type Person struct {
firstName, lastName string
}
有幾種不同的方式可以根據 struct 來建立變數的:
func main() {
// 方法一:根據資料輸入的順序決定誰是 firstName 和 lastName
alex := Person{"Alex", "Anderson"}
// 直接取得 struct 的 pointer
alex := &Person{"Alex", "Anderson"}
// 方法二(建議)
alex := Person{
firstName: "Alex",
lastName: "Anderson",
}
// 方法三:先宣告再賦值
var alex Person
alex.firstName = "Alex"
alex.lastName = "Anderson"
// 方法四
var alex = Person{
firstName: "Alex",
lastName: "Anderson",
}
}
輸出建立好的 struct:
// 如果希望一併輸出 field name 的話
fmt.Printf("%+v", alex) // {firstName:Alex lastName:Anderson}
fmt.Println(alex) // {Alex Anderson}
取值的方式:
alex.firstName // 不能用 alex["firstName"],因為 alex 是 struct,不是 map
alex.lastName
定義匿名的 struct(anonymous struct)
也可以不先宣告 struct 直接建立個 struct:
foo := struct {
Hello string
}{
Hello: "World",
}
當 pointer 指稱到的是 struct 時
當 pointer 指稱到的是 struct 時,可以直接使用這個 pointer 來對該 struct 進行設值和取值。在 golang 中可以直接使用 pointer 來修改 struct 中的欄位。一般來說,若想要透過 struct pointer(&v)來修改該 struct 中的屬性,需要先解出其值(*p)後使用 (*p).X = 10,但這樣做太麻煩了,因此在 golang 中允許開發者直接使用 p.X 的方式來修改:
type Person struct {
name string
age int32
}
func main() {
p := &Person{
name: "Aaron",
}
// golang 中允許開發者直接使用 `p.age` 的方式來設值與取值
p.age = 10 // 原本應該要寫 (*p).X = 10
fmt.Printf("%+v", p) // {name:Aaron age:10}
}
另外,使用 struct pointer 時才可以修改到原本的物件,否則會複製一個新的:
func main() {
r1 := rectangle{"Green"}
// 複製新的,指稱到不同位置
r2 := r1
r2.color = "Pink"
fmt.Println(r2) // Pink
fmt.Println(r1) // Green
// 指稱到相同位置
r3 := &r1
r3.color = "Red"
fmt.Println(r3) // Red
fmt.Println(r1) // Red
}
在 struct 內關聯另一個 struct(nested struct)
在一個 struct 內可以包含另一個 struct:
// STEP 1:定義外層 struct
type person struct {
firstName string
lastName string
contact contactInfo
}
// STEP 2:定義內層 struct
type contactInfo struct {
email string
zipCode int
}
func main() {
// STEP 3:建立變數
jim := person{
firstName: "Jim",
lastName: "Party",
contact: contactInfo{
email: "jim@gmail.com",
zipCode: 94000,
},
}
alex := person{
firstName: "Alex",
lastName: "Anderson",
}
// STEP 4:印出變數
fmt.Printf("%+v\n", jim) // {firstName:Jim lastName:Party contact:{email:jim@gmail.com zipCode:94000}}
fmt.Println(jim) // {Jim Party {jim@gmail.com 94000}}
fmt.Printf("%+v\n", alex) // {firstName:Alex lastName:Anderson contact:{email: zipCode:0}}
fmt.Println(alex) // {Alex Anderson { 0}}
}
Struct field Tag(meta-data)
struct field tag 會在 struct 的 value 後面使用 backtick 來表示,例如 json:"name"