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

那么来看一个应用例子:

package main

import (
"fmt"
"runtime"
"time"
) func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
} func main() {
ch := make(chan int, )
go func(ch chan int) {
for {
val := <-ch
fmt.Printf("val:%d\n", val)
}
}(ch) tick := time.NewTicker( * time.Second)
for i := ; i < ; i++ {
select {
case ch <- i:
case <-tick.C:
fmt.Printf("%d: case <-tick.C\n", i)
} time.Sleep( * 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:
val:
val:
val:
val:
: case <-tick.C
val:
val:
val:
val:
val:
: case <-tick.C
val:
val:
val:
val:
val:
: case <-tick.C
val:
val:
val:
val:
val:

golang 中的 time 包的 Ticker的更多相关文章

  1. golang中的reflect包用法

    最近在写一个自动生成api文档的功能,用到了reflect包来给结构体赋值,给空数组新增一个元素,这样只要定义一个input结构体和一个output的结构体,并填写一些相关tag信息,就能使用程序来生 ...

  2. golang中container/list包源码分析

    golang源码包中container/list实际上是一个双向链表 提供链表的一些基本操作,下面就结合定义和接口进行下说明 1. 定义 // Element is an element of a l ...

  3. golang中container/heap包源码分析

    学习golang难免需要分析源码包中一些实现,下面就来说说container/heap包的源码 heap的实现使用到了小根堆,下面先对堆做个简单说明 1. 堆概念 堆是一种经过排序的完全二叉树,其中任 ...

  4. golang中的rpc包用法

    RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. 我所在公司的项目是采用基于Restful的微服务架构,随着微服 ...

  5. golang中的context包

    标准库的context包 从设计角度上来讲, golang的context包提供了一种父routine对子routine的管理功能. 我的这种理解虽然和网上各种文章中讲的不太一样, 但我认为基本上还是 ...

  6. golang中net/http包的简单使用

    一.介绍 http包提供了http客户端和服务端的实现 Get,Head,Post和PostForm函数发出http.https的请求 程序在使用完回复后必须关闭回复的主体 #简单的访问网站,由于没有 ...

  7. golang中os/exec包用法

    exec包执行外部命令,它将os.StartProcess进行包装使得它更容易映射到stdin和stdout,并且利用pipe连接i/o. 1.func LookPath(file string) ( ...

  8. 关于Golang中database/sql包的学习

    go-sql-driver 请求一个连接的函数有好几种,执行完毕处理连接的方式稍有差别,大致如下: db.Ping() 调用完毕后会马上把连接返回给连接池. db.Exec() 调用完毕后会马上把连接 ...

  9. Golang中database/sql包

    驱动 github.com/go-sql-driver/mysql 请求一个连接的函数有好几种,执行完毕处理连接的方式稍有差别,大致如下: db.Ping() 调用完毕后会马上把连接返回给连接池. d ...

随机推荐

  1. 结对项目:SudokuGame

    1. Github项目地址:https://github.com/ZiJiaW/SudokuGame GUI在BIN目录下的SudokuGUI.rar中,解压后打开SudokuGame.exe即可.2 ...

  2. 20lanmo162326 2017-2018-1 《程序设计与数据结构》第1周学习总结

    20162326 2017-2018-1 <程序设计与数据结构>第1周学习总结 教材学习内容总结 算法:在特定计算模型下,解决问题的指令序列 计算 = 信息处理 也就是用工具,遵规则,机械 ...

  3. StringBuffer 与 StringBuilder类的使用

    /*如果需要频繁修改字符串 的内容,建议使用字符串缓冲 类(StringBuffer). StringBuffer 其实就是一个存储字符 的容器. 笔试题目:使用Stringbuffer无 参的构造函 ...

  4. beta冲刺(5/7)

    目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:恺琳 组员6:翟丹丹 组员7:何家伟 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4 ...

  5. Leetcode题库——7.反转整数

    @author: ZZQ @software: PyCharm @file: IntReverse.py @time: 2018/9/16 16:36 要求:整数反转(给定一个 32 位有符号整数,将 ...

  6. ssh框架配置数据源 数据库连接没有正常释放

    通过多天的改bug 对数据源这个东西了解多了..    我发现 spring+hibernate下  申请数据库连接是在一个action方法内  也就是说  action 里面有三个 service方 ...

  7. 【搜索】POJ-3187 枚举全排列

    一.题目 Description FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to ...

  8. python字符串操作、文件操作,英文词频统计预处理

    1.字符串操作: 解析身份证号:生日.性别.出生地等. 凯撒密码编码与解码 网址观察与批量生成 解析身份证号:生日.性别.出生地等 def function3(): print('请输入身份证号') ...

  9. Java& Vector与ArrayList区别

    在写java的时候,基本上都喜欢用arraylist,甚至我都不知道有个vector的存在.查了一下发现又是线程安全问题...咋个线程安全天天围着我转呢...多得阿里巴巴,让我开始认识java的所谓线 ...

  10. dotTrace快速帮助你定位C#代码的性能瓶颈

    dotTrace 1.     问题描述 IIS发布的接口运行一段时间后变的很慢,重启IIS连接池后问题得到解决,但是运行一段时间后再次出现变慢的问题 2.     问题原因 程序中有读取xml文件的 ...