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

在同一选定案例中接收和发送

在同一选定案例中接收和发送

Go
BIG阳 2022-08-30 21:51:53
我需要将一个通道的结果转发到另一个通道。我用了这样的东西:for {        select {        ...        case ch2 <- (<-ch1):        ...        }}这似乎很完美,但这里到底发生了什么?select 语句是在接收操作和/或发送操作上选择的?我知道选择语句可以单独选择:select {    case ch <- v:}select {                                                                             case v = <- ch:}
查看完整描述

2 回答

?
侃侃无极

TA贡献2051条经验 获得超10个赞

从文档中

对于语句中的所有情况,在输入 “select” 语句时,接收操作的通道操作数以及 send 语句的通道和右侧表达式将按源顺序计算一次。结果是一组要从中接收或发送到的通道,以及要发送的相应值。无论选择哪个(如果有)通信操作继续进行,都将发生该评估中的任何副作用。尚未计算 RecvStmt 左侧具有短变量声明或赋值的表达式。

这意味着:

case ch2 <- (<-ch1):

立即阻止从 接收,然后将控制是否发生发送或不同。ch1selectch2case

迪斯科的赞美诗说得很好;将其视为 ,其中在输入 时进行评估。selectch2 <- <something><something>select

它还具有消耗和丢弃值的副作用,如果该值最终不是所选的值。ch1case


查看完整回答
反对 回复 2022-08-30
?
函数式编程

TA贡献1807条经验 获得超9个赞

正如阿德里安所回答的那样,这绝对是错误的方法。如果您想在某个退出频道说退出之前接收和转发数据,则需要以下或类似内容:


func copyInputUntil(output, input chan T, quit chan struct{}) {

    for {

        var v T

        // wait for input value, or quit

        select {

        case <-quit: return // maybe: close(output), too (via earlier defer)

        case v = <-input:

        }

        // wait to send it

        select {

        case <-quit: return

        case output <- v:

        }

    }

}

这可以作为自己的goroutine剥离出来。这不太现实,当然这是低效的:你最好只是让发送者直接发送到正确的渠道,而不是让这个愚蠢的goroutine介于两者之间。


尽管如此,我还是把这一切都变成了围棋操场上一个完整的例子。


查看完整回答
反对 回复 2022-08-30
  • 2 回答
  • 0 关注
  • 101 浏览
慕课专栏
更多

添加回答

举报

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