为了账号安全,请及时绑定邮箱和手机立即绑定

带有通道和等待组的 Golang 选择语句

带有通道和等待组的 Golang 选择语句

Go
开满天机 2022-06-01 09:55:33
在使用 Golang 进行实验时,我创建了一个带有 select 语句的函数,它监听两个通道。我的问题是代码似乎表现得不确定——有时它会恐慌,有时它会成功完成。我的期望是这段代码应该总是恐慌。它应该首先收到错误,因为它应该在 waitGroup 完成之前调度,因此在成功通道被推送到之前。package mainimport (    "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}
查看完整描述

1 回答

?
互换的青春

TA贡献1797条经验 获得超6个赞

在 select 语句之前,两个通道都准备好了;因此它将通过统一的伪随机选择进行选择:


让我们替换doSomething代码中的函数调用,并将 defer 放在函数的末尾:


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()等待,代码(几乎)在功能上等于以下代码,并且两个通道在此处的 select 语句之前准备好: wg.Done()


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”语句会阻塞,直到至少有一个通信可以继续。


查看完整回答
反对 回复 2022-06-01
  • 1 回答
  • 0 关注
  • 81 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信