分享
  1. 首页
  2. 文章

golang 中的 time 包的 Ticker

liang1101 · · 7139 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

真实的应用场景是:在测试收包的顺序的时候,加了个 tick 就发现丢包了

那么来看一个应用例子:

package main
import (
 "fmt"
 "runtime"
 "time"
)
func init() {
 runtime.GOMAXPROCS(runtime.NumCPU())
}
func main() {
 ch := make(chan int, 1024)
 go func(ch chan int) {
 for {
 val := <-ch
 fmt.Printf("val:%d\n", val)
 }
 }(ch)
 tick := time.NewTicker(1 * time.Second)
 for i := 0; i < 20; i++ {
 select {
 case ch <- i:
 case <-tick.C:
 fmt.Printf("%d: case <-tick.C\n", i)
 } 
 time.Sleep(200 * time.Millisecond)
 }
 close(ch)
 tick.Stop()
}

输出结果如下:

val:0
val:1
val:2
val:3
val:4
val:5
6: case <-tick.C
val:7
val:8
val:9
10: case <-tick.C
val:11
val:12
val:13
val:14
15: case <-tick.C
val:16
val:17
val:18
val:19

问题出在这个select里面:

select {
 case ch <- i:
 case <-tick.C:
  fmt.Printf("%d: case <-tick.C\n", i)
}

[tick.C 介绍说明] 当两个 case 条件都满足的时候,运行时系统会通过一个伪随机的算法决定哪个case将会被执行。所以当 tick.C 条件满足的那个循环,有某种概率造成 ch<-i 没有发送(虽然通道两端没有阻塞,满足发送条件)

解决方案1:一旦 tick.C 随机的 case 被随机到,就多执行一次 ch<-i (不体面,如果有多个case就不通用了)

select {
 case ch <- i:
 case <-tick.C:
 fmt.Printf("%d: case <-tick.C\n", i)
 ch <- i
}

解决方案2:将tick.C的case单独放到一个select里面,并加入一个default(保证不阻塞)

select {
 case ch <- i:
}
select {
 case <-tick.C:
 fmt.Printf("%d: case <-tick.C\n", i)
 default:
}

两种解决方案的输出都是希望的结果:

val:0
val:1
val:2
val:3
val:4
5: case <-tick.C
val:5
val:6
val:7
val:8
val:9
10: case <-tick.C
val:10
val:11
val:12
val:13
val:14
15: case <-tick.C
val:15
val:16
val:17
val:18
val:19

有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:liang1101

查看原文:golang 中的 time 包的 Ticker

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
7139 次点击
1 回复 | 直到 2025年05月09日 13:36:13
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏