> For the complete documentation index, see [llms.txt](https://go.netdpi.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://go.netdpi.net/concurrency/10.01-goroutine.md).

# 10.01-Goroutine

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

```go
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：

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

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

```go
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 現在應該會同步執行了。
