# Day10 繼續Go-基本組合型別2(map, struct) ## 映射 Map #### 【map】 `map`有很多種翻譯,名詞叫作`地圖`,動詞有`映射`、`對應`、`對照`的意思 ,在一些程式語言中則有`Key-Value`一個關鍵字對應一個值的用法。 > **var Variable = map[Type]Type{}** >> var a = map[int]string{} https://play.golang.org/p/dAgwOEXq6sN 可以像這樣`bool`對應到任何`string` ```go var Male = map[bool]string{ true: "公", false: "母", } ``` 或是設定`string`對應到`int` ```go var Number = map[string]int{ "零": 0, "壹": 1, "貳": 2, } Number["參"] = 3 ``` `string`對應到`string`也可以, ```go var Size = map[string]string{ "big": "大", "medium": "中", "small": "小", } ``` 只要任兩種型態設定好、對應好之後就能用哩, `string`的前後要加雙引號`" "`,來試試效果吧! #### 取map ```go fmt.Print(Male[true],Number["參"]) /* result: 公3 */ ``` ### 【for 迭代遍歷】 透過`for range`關鍵字,遍歷造訪結構內的每個元素 ```go for key, value := range Size { fmt.Println(key, value) } /* result: big 大 medium 中 small 小 */ ``` ## 結構 Struct #### 【struct】 結構裡面可以放多個變數(`int`、`string`、`slice`、`map`等等)、物件、甚至是結構。 宣告結構`Struct`的幾種方式: https://play.golang.org/p/lEeUmceDsjh ```go package main import "fmt" type Res struct { Status string Msg string } func main() { res1 := new(Res) var res2 = new(Res) var res3 *Res res4 := &Res{ Status: "failed", } fmt.Println(res1, res2, res3, res4) fmt.Printf("%+v %+v %+v %+v", res1, res2, res3, res4) } /* result: &{ } &{ } <nil> &{failed } &{Status: Msg:} &{Status: Msg:} <nil> &{Status:failed Msg:} */ ``` #### 【Nested Structure】巢狀結構 `結構中的結構的結構`、大腸包小腸再包小小腸 https://play.golang.org/p/Bd85fmF10Uo ```go type Wallet struct { Blue1000 int // 藍色小朋友 Red100 int // 紅色國父 Card string } type PencilBox struct { Pencil string Pen string } type Bag struct { Wallet // 直接放入結構就好 PencilBox // 直接放入結構就好 Books string } type Person struct { Bag Name string } func main() { var bag = Bag{ Wallet{Card: "世華泰國信用無底洞卡", Red100: 5}, PencilBox{Pen: "Cross", Pencil: "Pentel"}, "Go繁不及備載", // Books } var Tommy = Person{} Tommy.Name = "Tommy" Tommy.Bag = bag fmt.Printf("%+v", Tommy) } /* result: {Bag:{Wallet:{Blue1000:0 Red100:5 Card:世華泰國信用無底洞卡} PencilBox:{Pencil:Pentel Pen:Cross} Books:Go繁不及備載} Name:Tommy} */ ``` 藝涔 益晨 翊誠~ 的剝開我的Struct... --- ## 【指標、結構、位址】 這裡將上面的例子取一部分出來修改, 如果將`main()`裡的`var Bag`敘述改成 `&Bag`: ```go type Person struct { Bag // 放Bag這個物件 Name string } func main() { var bag = &Bag{ Wallet{Card: "世華泰國信用無底洞卡", Red100: 5}, PencilBox{Pen: "Cross", Pencil: "Pentel"}, "Go繁不及備載", } var Tommy = Person{} Tommy.Name = "Tommy" Tommy.Bag = *bag // 透過`取值`來取出bag位址裡面的東西 fmt.Printf("%+v", Tommy) } /* result: {Bag:{Wallet:{Blue1000:0 Red100:5 Card:世華泰國信用無底洞卡} PencilBox:{Pencil:Pentel Pen:Cross} Books:Go繁不及備載} Name:Tommy} */ ``` 印出bag 就要透過`*`來取值 --- 如果將`Person`裡的`Bag`改成 `*Bag`: ```go type Person struct { *Bag // 放指標 Name string } func main() { var bag = &Bag{ // 指到位址 Wallet{Card: "世華泰國信用無底洞卡", Red100: 5}, PencilBox{Pen: "Cross", Pencil: "Pentel"}, "Go繁不及備載", } var Tommy = Person{} Tommy.Name = "Tommy" Tommy.Bag = bag // 這裡就印出bag位址 fmt.Printf("%+v", Tommy) } /* result: {Bag:0xc000048050 Name:Tommy} */ ``` 這樣子就會印出`bag`的位址 --- 雖然有點**違反物理法則及常識**,但 #### 【小坑】如果Bag裡面有PencilBox,PencilBox裡面又有Bag 會怎麼樣呢? 答案是出現 `invalid recursive type` 的錯誤。 https://play.golang.org/p/KS5IvIgF1BQ ```go type PencilBox struct { Pencil string Pen string Bag // 你中有我 我中有你 } type Bag struct { Wallet PencilBox Books string } ``` 雖然放物件會出現錯誤,但是 `放指針`不會 https://play.golang.org/p/mXbp60WDXtR ```go type PencilBox struct { Pencil string Pen string *Bag // 你中有針 } type Bag struct { Wallet PencilBox Books string } func main() { var bag = Bag{ Wallet{Card: "世華泰國信用無底洞卡", Red100: 5}, PencilBox{Pen: "Cross", Pencil: "Pentel"}, "Go繁不及備載", } bag.PencilBox.Bag = &bag // 包包裡放針 fmt.Printf("%+v", *bag.PencilBox.Bag) } /* result: {Wallet:{Blue1000:0 Red100:5 Card:世華泰國信用無底洞卡} PencilBox:{Pencil:Pentel Pen:Cross Bag:0xc000046060} Books:Go繁不及備載} */ ```