iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 6
1
Software Development

Go Phishing!30 天用 Go 實作 Reverse Proxy 之釣魚大作戰系列 第 6

Day06-Go 語法 II

Slice

Slice 就像 JS/Python 的 Array 或是 C++ 的 Vector,可以使用 append 增加元素、用 len 取得長度

Run

func main() {
    arr := []int{0, 1, 2, 3}
    fmt.Println(arr)    // [0 1 2 3]

    arr = append(arr, 4, 5)
    fmt.Println(arr)        // [0, 1, 2, 3, 4, 5]
    fmt.Println(arr[1:4])   // [1, 2, 3]
    fmt.Println(arr[1:])    // [1, 2, 3, 4, 5]

    // len = 6
    fmt.Println("len =", len(arr))
}

Map

Go 的 Map 是一個 key/value 的結構,就像 JS 的 object、python 的 dict、C++ 的 unordered_map

Run

func main() {
    m := map[string]int{"zero": 0}
    
    m["one"] = 1
    m["two"] = 2

    fmt.Println(m["zero"])  // 0
    fmt.Println(m["one"])   // 1
}

Range

對於 Slice 跟 Map 這種儲存多筆資料的資料結構,可以使用 range 來遍歷他

Run

func main() {
    arr := []int{0, 1, 2}
    
    for i, n := range arr {
        fmt.Printf("arr[%d] = %d\n", i, n)
        // arr[0] = 0
        // arr[1] = 1
        // arr[2] = 2
    }
    
    m := map[string]int{}
    m["one"] = 1
    m["two"] = 2
    
    for k, v := range m {
        fmt.Printf("%s -> %d\n", k, v)
        // one -> 1
        // two -> 2
    }
}

Struct

在 Go 裡面沒有物件導向所以自然沒有 class,但可以用 struct 做到差不多的功能,來看看這個計算長方形面積的例子。func (r Rectangle) Area() int 的意思是這是 Rectangle 的 method,這個 method 叫做 Area(),回傳值是 int

Run

type Rectangle struct {
    H int
    W int
}

func (r Rectangle) Area() int {
    return r.H * r.W
}

func main() {
    rec := Rectangle{H: 10, W: 5}
    fmt.Println(rec.Area()) // 10 x 5 = 50
    
    rec.W = 10
    fmt.Println(rec.Area()) // 10 x 10 = 100
}

Pointer

因為很多語言是沒有指標的,所以這邊不會講得太深入,只會稍微提一下使用情境

Run

setW10 中,這個 r 其實是 rec 的複製品,改 r.W = 10 並不會改到 rec,所以 rec 的面積還是 10 x 5 = 50

但如果像 setW20 的參數型別是 *Rectangle,那就不會多複製一份,r 就是原本的 rec,所以 r.W = 20 會改到原本的 rec,面積就變成 10 x 20 = 200

func setW10(r Rectangle) {  // 這個 r 是複製品
    r.W = 10                // 改了複製品卻沒有改到原本的 rec
}

func setW20(r *Rectangle) { // 這個 r 就是 rec
    r.W = 20                // 改他就會改到 rec
}

func main() {
    rec := Rectangle{H: 10, W: 5}
    fmt.Println(rec.Area()) // 10 x 5 = 50

    setW10(rec)             // 原本的 rec 沒有被改到
    fmt.Println(rec.Area()) // 10 x 5 = 50
	
    setW20(&rec)            // 原本的 rec 被改到了
    fmt.Println(rec.Area()) // 10 x 20 = 200
}

小練習

試試看到 Go Playground 上實作 func (r Rectangle) Pemi() int 計算長方形的周長:

題目

type Rectangle struct {
    H int
    W int
}

func (r Rectangle) Pemi() int {
    // Implement this function
}

func main() {
    rec := Rectangle{H: 10, W: 5}
    
    // pemi: 30
    fmt.Println("pemi:", rec.Pemi())
}

解答

小結

今天講的 slice、map 跟 struct 大家都看懂了嗎?這些在之後實作的時候會很常用到,所以務必要看懂哦。有任何問題歡迎在下方留言,沒問題明天就要進入 Go 最擅長的部份 - 併發


上一篇
Day05-Go 語法 I
下一篇
Day07-Go 語法 III
系列文
Go Phishing!30 天用 Go 實作 Reverse Proxy 之釣魚大作戰30

尚未有邦友留言

立即登入留言