簡體   English   中英

帶有通道和等待組的 Golang select 語句

[英]Golang select statement with channels and waitgroup

用 Golang 進行實驗,我創建了一個 function 和一個 select 語句,它監聽兩個通道。

我的問題是代碼似乎表現得不確定——有時它會恐慌,有時它會成功完成。

我的期望是這段代碼應該總是恐慌。 它應該首先收到錯誤,因為它應該在 waitGroup 完成之前調度,因此在成功通道被推送到之前。

package main

import (
    "errors"
    "fmt"
    "sync"
)

func main() {
    errs := make(chan error, 1)
    success := make(chan bool, 1)

    doSomething(success, errs)

    select {
    case err := <-errs:
        fmt.Println("error", err)
        panic(err)
    case <-success:
        fmt.Println("success")
    }
    fmt.Println("finished successfully")
}

func doSomething(success chan bool, errs chan error) {
    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        err := errors.New("Some error")
        errs <- err
    }()

    wg.Wait()
    success <- true
}

在 select 語句之前,兩個通道都准備好了; 因此它將通過統一的偽隨機選擇進行選擇

讓我們替換代碼中的doSomething function 調用,並將 defer 放在 function 的末尾:

package main

import (
    "errors"
    "fmt"
    "sync"
)

func main() {
    errs := make(chan error, 1)
    success := make(chan bool, 1)

    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        err := errors.New("some error")
        errs <- err
        wg.Done()
    }()

    wg.Wait()
    success <- true

    select {
    case err := <-errs:
        fmt.Println("error", err)
        panic(err)
    case <-success:
        fmt.Println("success")
    }
    fmt.Println("finished successfully")
}

正如您在上面的代碼示例中看到的那樣,主 goroutine 在wg.Wait()處等待wg.Done()在這個時間點代碼(幾乎)在功能上等於以下代碼,並且兩個通道都准備好了在 select 語句之前:

package main

import (
    "errors"
    "fmt"
)

func main() {
    errs := make(chan error, 1)
    success := make(chan bool, 1)
    errs <- errors.New("some error")
    success <- true

    select {
    case err := <-errs:
        fmt.Println(err)
    case <-success:
        fmt.Println("success")
    }
}

跑:

$ go run .
some error

$ go run .
success

選擇語句

如果一個或多個通信可以進行,則通過統一的偽隨機選擇選擇一個可以進行的通信。 否則,如果存在默認情況,則選擇該情況。 如果沒有默認情況,“select”語句會阻塞,直到至少有一個通信可以繼續。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM