1 Preface

我们在 Linux 服务端编程的时候,select/epoll 可以监控多个fd, 并且可以指定超时时间。 那么我们在Go 里面也有select 关键字,那么怎么实现超时机制呢?

在 select 中加入一个 timer channel

case rc2 := <-time.After(d):

After等待持续时间过去,然后在返回的通道上发送当前时间。 它等效于NewTimer(d)。 在计时器触发之前,底层的计时器不会由垃圾收集器恢复。 如果需要提高效率,请改用NewTimer,如果不再需要计时器,请调用Timer.Stop。

完整代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 采用 select 实现超时
func TestSelectTimeOut(t *testing.T) {
    ch01 := make(chan int)
    go func(ch01 chan int) {
        fmt.Println("enter co-routine...")
        isRunning := true
        for isRunning {
            select {
            case rc1, ok := <-ch01:
                fmt.Println("rc1", rc1)
                if ok == false {
                    isRunning = false
                    fmt.Println("channel closed")
                }
            case rc2 := <-time.After(time.Millisecond * 200):
                fmt.Println("time out 1 sec", rc2)
            }
        }
        fmt.Println("exit co-routine...")
    }(ch01)
    time.Sleep(time.Second * 2)
    // 2秒之后发送一个消息
    ch01 <- 10
    close(ch01)
}

总结

Go 语言通过 channel 实现了很强大的功能, 使得编程更灵活易用,降低了学习门槛; 在 Linux C 里面高效的做法,采用epoll去做timer 的等待。

那么 Go 里面的 timer 的实现原理是怎样的呢? 且听后续分解。

《全文完》