繁体   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