10.01-Goroutine

Goroutines

Goroutine 是一個函式,可以與其它函式同步執行,我們可以使用 go 關鍵字建立一個 goroutine,並接著一個函式呼叫:

package main

import "fmt"

func f(n int) {
    for i := 0; i < 10; i++ {
        fmt.Println(n, ":", i)
    }
}

func main() {
    go f(0)
    var input string
    fmt.Scanln(&input)
}

這個程式有兩個 goroutines,第一個 goroutine 是隱含的(implicit),即是 main 函式自己,第二個 goroutine 是我們呼叫 go f(0) 時建立的。通常當我們呼叫一個函式時,我們的程式會執行函式中的每一行程式碼,並回到原本呼叫函式的地方。但是透過 goroutine,我們可以在呼叫函式之後,直接執行下一行程式,而不用等待函式完成。這就是為什麼需要呼叫 Scanln 函式,如果沒有這個函式,程式在還沒來得及印出全部的數字以前就會結束了。

Goroutines 是輕量級的,而且我們可以輕易的建議數千個,現在我們如下修改程式,讓它可以執行 10 個 goroutines:

func main() {
    for i := 0; i < 10; i++ {
        go f(i)
    }
    var input string
    fmt.Scanln(&input)
}

你可能注意到了,當你執行這個程式時,程式似乎是依序執行 goroutine,而不是同步執行。我們現在使用 time.Sleep 與 rand.Intn 在函式中新增一些延遲時間:

package main

import (
    "fmt"
    "time"
    "math/rand"
)

func f(n int) {
    for i := 0; i < 10; i++ {
        fmt.Println(n, ":", i)
        amt := time.Duration(rand.Intn(250))
        time.Sleep(time.Millisecond * amt)
    }
}
func main() {
    for i := 0; i < 10; i++ {
        go f(i)
    }
    var input string
    fmt.Scanln(&input)
}

f 會印出 0 到 10 的數字,每輸出一個數字就隨機等待一段時間(0 ~ 250 ms),這些 routines 現在應該會同步執行了。

Comments