Skip to main content

Goroutine

  • 檢查有沒有 race condition
go run -race main.go

WaitGroup

用於等待一系列的 goroutine 完成任務

方式:communicating by sharing memory

常用方法

Add: 在 main goroutine 中呼叫

Done: 在其它新建的 goroutine 中呼叫

Wait: 可以 block 直到其他 goroutine 完成

Example

  • WaitGroup 全域宣告
    package main

    import (
    "fmt"
    "sync"
    )

    var (
    wg sync.WaitGroup
    )

    func main() {
    wg.Add(1)

    go compute(5)

    fmt.Println("Hello")

    wg.Wait()
    }

    func compute(number int) {
    total := 0

    for i := 0; i < number; i++ {
    total += i
    }
    fmt.Println(total)

    wg.Done()
    }

  • WaitGroup 區域宣告,要傳 pointer 進去
    package main

    import (
    "fmt"
    "sync"
    )

    func main() {
    var wg sync.WaitGroup
    wg.Add(1)

    go compute(5, &wg)

    fmt.Println("Hello")

    wg.Wait()
    }

    // wg 要傳 pointer,才會改到同一個
    func compute(number int, wg *sync.WaitGroup) {
    total := 0

    for i := 0; i < number; i++ {
    total += i
    }
    fmt.Println(total)

    wg.Done()
    }

Channel

  • share memory by communicating

有分以下兩種:

  • Unbuffered Channel 讀寫要在不同 goroutine
    package main

    import (
    "fmt"
    )

    func main() {
    ch := make(chan int)

    go compute(5, ch)

    result := <-ch
    fmt.Println("receive:", result)
    }

    func compute(number int, ch chan<- int) {
    total := 0

    for i := 0; i < number; i++ {
    total += i
    }

    ch <- total
    }

  • Buffered Channel 只要容量沒滿,就可以一直塞東西進去,可以在同一個 goroutine 一直讀寫
    package main

    import "fmt"

    func main() {
    c := make(chan bool, 1)
    go func() {
    fmt.Println("hello world")
    <-c
    }()
    c <- true
    }
    此範例不會 block,true 丟進去 channel 後,就直接結束,不會印出任何東西

close: 表示 channel 不能再被寫入,可讀取

  • Close (待補齊!!) channel 取值時,可以有第二個參數 ok,來判斷 channel 是否 close
    result, ok := <-c

    if ok {
    fmt.Println("is open")
    } else {
    fmt.Println("is close")
    }
    • 有無 close,讀值 > 存值

      close


      not close


Reference