什麼是 Goroutine#

Goroutine 是 Go 的輕量級執行緒,由 Go 執行時期(Runtime)管理,而非作業系統。

func sayHello(name string) {
    fmt.Println("Hello,", name)
}

func main() {
    // 啟動 goroutine
    go sayHello("World")

    // 使用匿名函式
    go func() {
        fmt.Println("匿名 goroutine")
    }()

    // 等待 goroutine 完成(實際使用 sync.WaitGroup)
    time.Sleep(time.Second)
}

Goroutine 與 OS 執行緒的差異

  • Goroutine 初始堆疊只有 2KB(執行緒通常 1–8MB)
  • 由 Go runtime 排程,切換成本極低
  • 可以輕鬆建立數十萬個 goroutine

G-P-M 排程模型#

Go 排程器使用 G-P-M 模型:

  • G(Goroutine):要執行的 goroutine
  • P(Processor):邏輯處理器,預設數量等於 CPU 核心數
  • M(Machine):作業系統執行緒
flowchart LR
    subgraph Goroutines
        G1[G1]
        G2[G2]
        G3[G3]
        G4[G4]
        G5[G5]
        G6[G6]
    end

    subgraph Processors
        P1[P1]
        P2[P2]
    end

    subgraph OS Threads
        M1[M1]
        M2[M2]
    end

    G1 --> P1
    G2 --> P1
    G3 --> P1
    G4 --> P2
    G5 --> P2
    G6 --> P2
    P1 --> M1
    P2 --> M2
設定並行數量
import "runtime"

func main() {
    // 查詢 CPU 核心數
    numCPU := runtime.NumCPU()

    // 設定可用的邏輯處理器數量
    runtime.GOMAXPROCS(numCPU)

    // Go 1.5+ 預設使用所有 CPU 核心
}

生命週期#

func main() {
    go worker()  // 啟動 goroutine

    // 主 goroutine 結束 → 程式立即終止
    // 不會等其他 goroutine 完成!
}

func worker() {
    for i := 0; i < 10; i++ {
        fmt.Println(i)
        time.Sleep(time.Millisecond * 100)
    }
}

main 函式回傳時,整個程式會立即終止,不會等其他 goroutine 完成。必須用適當的同步機制(WaitGroup、Channel)協調 goroutine。