Go Concurrency Patterns: Timing out, moving on

原文地址:https://blog.golang.org/concurrency-timeouts

并发变成有它自己的风格. 一个非常好的例子就是 timeout. 虽然 go 的 channel 没有直接支持 timeout 机制,但是要实现它非常容易.

比如说,我们想从一个 channel ch 中接收数据,但是最多只想等待 1 秒. 我们可以这么做:创建一个 channel 作为信号 channel (signalling channel), 再创建一个 goroutine,这个 goroutine 再发送数据之前先休眠 1 秒.

timeout := make(chan bool, 1)
go func() {
    time.Sleep(1 * time.Second)
    timeout <- true
}()

然后,我们使用 select 语句来从 ch 上接受数据. 如果在 1 秒之后,ch 上没有数据到来,那么我们将会进入timeout 分支.

select {
case <-ch:
    // a read from ch has occurred
case <-timeout:
    // the read from ch has timed out
}

timeout channel 的 buffer 大小为 1, 当 goroutine 发送了 timeout 信号之后,便退出了. goroutine 并不知道它发送的超时信号是否已经被接受,这意味着,如果 在 1秒之内,成功的从 ch 上收到了数据, goroutine 不会因为等待它发送到 timeout channel 上的信号被接受而永远阻塞.

接下来,我们来看一下这个模式的一种变体. 在这个例子中,我们的程序从多个数据库中同时读取数据. 它仅仅需要一个结果,因此它只会接收最先到达的数据.

Query 输入一个数据库连接的集合和一个查询字符串,它会同时查询这些数据库,接收第一个查询结果.

func Query(conns []Conn, query string) Result {
    ch := make(chan Result)
    for _, conn := range conns {
        go func(c Conn) {
            select {
            case ch <- c.DoQuery(query):
            default:
            }
        }(conn)
    }
    return <-ch
}

这个方法中,我们为每个数据库查询操作开启一个 goroutine,在 goroutine 中以非阻塞模式返送请求,等待查询结果. 为每个数据库连接使用一个单独 goroutine 确保了一个操作不会影响另一个操作,这些操作并行进行.

END!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值