go中select中使用time.After的小bug

time.After

在go中使用select时用time定义定时器的时候遇到的一个小问题,记录下

先说要求:

  1. 在控制台打印0-29的数字, 每隔1s打印一个

  2. 打印完成后, sleep10s, 然后打印"结束了", 退出程序

再看下面两份代码

A:

package main
​
import (
    "fmt"
    "time"
)
​
​
func main() {
    // 定义channel
    C := make(chan int64, 10)
    // 使用一个goroutine每隔1s向C中send一个数
    go func() {
        // goroutine退出关闭C
        defer close(C)  
        var i int64
        for i = 0; i < 30; i++ {
            C <- i
            time.Sleep(time.Second * 1)
        }
    }()
    // 循环receive C 中的数,并作超时处理
    for {
        select {
        case i := <-C:
            fmt.Println("num: ", i)
        case <- time.After(time.Second * 10):   // 注意点, 就是这里
            fmt.Println("结束了")
            return
        }
    }
}

B:

package main
​
import (
    "fmt"
    "time"
)
​
​
func main() {
    // 定义channel
    C := make(chan int64, 10)
    // 使用一个goroutine每隔1s向C中send一个数
    go func() {
        // goroutine退出关闭C
        defer close(C)  
        var i int64
        for i = 0; i < 30; i++ {
            C <- i
            time.Sleep(time.Second * 1)
        }
    }()
    // 定义一个定时器
    timer := time.After(time.Second * 10)
    // 循环receive C 中的数,并作超时处理
    for {
        select {
        case i := <-C:
            fmt.Println("num: ", i)
        cacase <- timer:    // 注意点, 就是这里
            fmt.Println("结束了")
            return
        }
    }
}

具体执行结果如下:

A:

PS F:\CZproject\spiderman\test_go> go run "f:\CZproject\spiderman\test_go\main\main.go"
num:  0
num:  1
num:  2
num:  3
num:  4
num:  5
num:  6
num:  7
num:  8
num:  9
num:  10
num:  11
num:  12
num:  13
num:  14
num:  15
num:  16
num:  17
num:  18
num:  19
num:  20
num:  21
num:  22
num:  23
num:  24
num:  25
num:  26
num:  27
num:  28
num:  29
结束了

B:

PS F:\CZproject\spiderman\test_go> go run "f:\CZproject\spiderman\test_go\main\main.go"
num:  0
num:  1
num:  2
num:  3
num:  4
num:  5
num:  6
num:  7
num:  8
num:  9
结束了

比较会发现第二份打印输出内容比第一份少了许多, 并不满足我们提的需求.

为什么呢?

关键点就在于定时器的声名节点以及执行节点,就是定时器在何时定义, 以及在什么时候开始计时

到了这里, 聪明的小伙伴就明白了, 第二份代码中定时器开始计时的时间节点出问题了

没错, 就是这样, 在第二份代码中, 在执行"timer := time.After(time.Second * 10)"的时候,定义定时器timer, 但在这个时候,注意了, 这个时候定时器已经开始计时了, 当过了10s后, 在执行"case <- timer", 发现已经超时了, 那么就结束吧 再来看第一份代码, 这里是在"case <- time.After(time.Second * 10)"定义定时器并开始计时, 但是注意了,这里时每执行到这一行代码时, 都会定义一个定时器并开始计时 .

就好比有两个员工A和B, 假如两个员工的忍耐极限都是10s, 现在给每个人都分配了30项工作,

A: 耐心好, 只要不是让连续干10s, 那我就能一致干下去

B: 耐心差, 我都干了10s了, 不干了, 走人...

今天就到这里了, 可爱的小伙伴别忘了点赞!!!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值