# 來學點 Go !! ###### tags: `Go` ### 前情提要 * 資料參考 > [初學 Golang 30 天](https://ithelp.ithome.com.tw/articles/10155678) > [Go by Exampl](https://gobyexample.com) > [ZetCode: Go interface](https://zetcode.com/golang/interface/) * 分點章節 > [來學點 Go !](/PHSJz1oER0S1Z4COWM0eyA) > [來學點 Go !!](/V39Yd1B1RK-fUjAYEyJJLQ) ### 寫點什麼涵式 (func) * 簡單的加減 ```go package main import ( "fmt" "math/rand" ) func main() { // 取亂數 n1, n2 n1 := rand_int() n2 := rand_int() // 亂數相加 sum := add(n1, n2) fmt.Println(n1, `+`, n2, `=`, sum) // 取得一個新亂數 rn := rand_int() // 暫存計算前的和數 sum rs := fmt.Sprintf(`%d - %d =`, sum, rn) // 計算減 併 印出結果 sum = sub(sum, rn) fmt.Println(rs, sum) } // 簡單的加 func add(n1 int, n2 int) int { return n1 + n2 } // 簡單的減 func sub(n1 int, n2 int) int { return n1 - n2 } // 簡單的亂數 func rand_int() int { /** * 直接用 rand.Intn 會發現都是取得固定的 81, 87, .... * 所以需要用點不一定的方法 * 設置亂數種子 seed, 來源 timestamp * ex: 1634622793227340319 * 然後用亂數種子為樣本取得新亂數 */ seed := rand.NewSource(time.Now().UnixNano()) return rand.New(seed).Intn(100) } ``` ### 踩點什麼錯誤 (error) * 簡單的加減有可能出現這樣的結果 ```shell $ go run main.go 0 + 4 = 4 4 - 31 = -27 ``` * 那是不是該加點什麼避免出現負數呢! ```go /** * 加個檢查式 * * 注意: * 這邊回傳用了 多參數回傳 * 所以要記得 回傳型別也要跟著改變 */ func is_positive_int(n int) (bool, error) { if n < 0 { return true, errors.New("必須是正整數!") } return false, nil } ``` * 主程序加個判斷式 ```go func main() { // 取亂數 n1, n2 n1 := rand_int() n2 := rand_int() // 亂數相加 sum := add(n1, n2) fmt.Println(n1, `+`, n2, `=`, sum) // 取得一個新亂數 rn := rand_int() // 暫存計算前的和數 sum rs := fmt.Sprintf(`%d - %d =`, sum, rn) // 計算減 併 印出結果 sum = sub(sum, rn) // 判斷計算結果 if _, err := is_positive_int(sum); err != nil { fmt.Println(err) // 發生錯誤,終止程序 os.Exit(1) } // 印出結果 fmt.Println(rs, sum) } ``` ### 自定點什麼結構 (struct) * 使用者嘛,總是會有那幾樣... ```go type user struct { // 名字啦 name string // 手機啦 phone string // 年齡啦 age int // 什麼啦 subscription bool } func main() { fmt.Println(user{"使用者1號", "09蝦咪啦", 26, false}) // {使用者1號 09蝦咪啦 26 false} fmt.Println(user{"使用者2號", "", 32, true}) // {使用者2號 32 true} fmt.Println(user{"使用者3號", "", 0, false}) // {使用者3號 0 false} } ``` ### 追加點什麼方法 (method) * 年紀到了總會被說...老了 ```go type people struct { name string age int } func main() { // 建立一個 people 的陣列 peoples := []people{ people{"1號", 72}, people{"2號", 63}, people{"3號", 54}, people{"4號", 45}, people{"5號", 36}, } // 透過 range 跑陣列迴圈 for k, v := range peoples { fmt.Printf("[%v] %v\n", k, v.age_stage()) } /** * 印出結果 * [0] 1號正處於 七十古來稀 * [1] 2號正處於 六十耳順 * [2] 3號正處於 五十知天命 * [3] 4號正處於 四十不惑 * [4] 5號正處於 三十而立 */ } // 對結構 people 追加一個年齡階段 age_stage 的方法 func (p people) age_stage() string { r := p.name + "正處於" switch { case p.age >= 70: r += " 七十古來稀" case p.age >= 60: r += " 六十耳順" case p.age >= 50: r += " 五十知天命" case p.age >= 40: r += " 四十不惑" case p.age >= 30: r += " 三十而立" case p.age < 30: r += " 屁孩一個" } return r } ``` ### 實作點什麼介面 (interface) * 多數的動物都會叫! ```go // 宣告一個動物 anime的介面 type anime interface { sound() string } // 宣告狗的結構 type dog struct {} // 對狗追加 sound 的方法 func (anime dog) sound() string { return "汪!" } // 宣告貓的結構 type cat struct {} // 對貓追加 sound 的方法 func (anime cat) sound() string { return "喵!" } // 宣告牛的結構 type cow struct {} // 對牛追加 sound 的方法 func (anime cow) sound() string { return "哞!" } // 煮程序 func main() { // 宣告動物們的變數, 且初始賦予 狗, 貓, 牛 animes := []anime{dog{}, cat{}, cow{}} // 用迴圈跑資料, 這邊因為不會用到 key 所以用了 _ 來代表接收回應但不使用 for _, val := range animes { fmt.Println("叫聲是", val.sound()) } /** * 印出結果 * 叫聲是 汪! * 叫聲是 喵! * 叫聲是 哞! */ } ``` ###