golang 中的 time 包的 Ticker
真实的应用场景是:在测试收包的顺序的时候,加了个 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的更多相关文章
- golang中的reflect包用法
最近在写一个自动生成api文档的功能,用到了reflect包来给结构体赋值,给空数组新增一个元素,这样只要定义一个input结构体和一个output的结构体,并填写一些相关tag信息,就能使用程序来生 ...
- golang中container/list包源码分析
golang源码包中container/list实际上是一个双向链表 提供链表的一些基本操作,下面就结合定义和接口进行下说明 1. 定义 // Element is an element of a l ...
- golang中container/heap包源码分析
学习golang难免需要分析源码包中一些实现,下面就来说说container/heap包的源码 heap的实现使用到了小根堆,下面先对堆做个简单说明 1. 堆概念 堆是一种经过排序的完全二叉树,其中任 ...
- golang中的rpc包用法
RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. 我所在公司的项目是采用基于Restful的微服务架构,随着微服 ...
- golang中的context包
标准库的context包 从设计角度上来讲, golang的context包提供了一种父routine对子routine的管理功能. 我的这种理解虽然和网上各种文章中讲的不太一样, 但我认为基本上还是 ...
- golang中net/http包的简单使用
一.介绍 http包提供了http客户端和服务端的实现 Get,Head,Post和PostForm函数发出http.https的请求 程序在使用完回复后必须关闭回复的主体 #简单的访问网站,由于没有 ...
- golang中os/exec包用法
exec包执行外部命令,它将os.StartProcess进行包装使得它更容易映射到stdin和stdout,并且利用pipe连接i/o. 1.func LookPath(file string) ( ...
- 关于Golang中database/sql包的学习
go-sql-driver 请求一个连接的函数有好几种,执行完毕处理连接的方式稍有差别,大致如下: db.Ping() 调用完毕后会马上把连接返回给连接池. db.Exec() 调用完毕后会马上把连接 ...
- Golang中database/sql包
驱动 github.com/go-sql-driver/mysql 请求一个连接的函数有好几种,执行完毕处理连接的方式稍有差别,大致如下: db.Ping() 调用完毕后会马上把连接返回给连接池. d ...
随机推荐
- 欢迎来怼--第三十七次Scrum会议
一.小组信息 队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 小组照片 二.开会信息 时间:2017/12/3 17:50~18:23,总计33min. 地点 ...
- 团队博客作业Week5 --- 团队贡献分--分配规则
团队会议 时间:公元2015年10月26日22时3分20秒 地点:宿舍楼716房间 与会人员:陈谋,李剑锋,卢惠民,刘夕霆,仉伯龙,潘成鼎. 会议内容:今天的组会主要讨论的是项目团队贡献分的计算方式, ...
- iOS 开发学习-import和include的区别
//当我们在代码中使用两次#include的时候会报错:因为#include相当于拷贝头文件中的声明内容,所以会报重复定义的错误 //但是使用两次#import的话,不会报错,所以他可以解决重复导入的 ...
- C++课程 second work _1025
传送门 Problem 题目不是特别难,只是跪在了最后一个测试点(已解决). 最后一个测试点= = 无效节点...无力ing
- mysql非安装包安装教程
设置mysql的环境变量 本人设置安装的路径是:E:\WebApplication\webMySQL\mysql-5.7.13-winx64 我的电脑 ---> 高级系统配置 ---> 环 ...
- 读《构建之法》一、二、十六章随笔a
第一章 概论 “软件团队要从需求分析开始,把合适的需求梳理出来,然后逐步开展后续工作”:——p3 问题:好的用户体验要从软件分析开始,那么软件分析仅仅是从用户的需求出发吗? 我的看法:需求分析是 ...
- 深入理解JAVA I/O系列三:字符流详解
字符流为何存在 既然字节流提供了能够处理任何类型的输入/输出操作的功能,那为什么还要存在字符流呢?容我慢慢道来,字节流不能直接操作Unicode字符,因为一个字符有两个字节,字节流一次只能操作一个字节 ...
- Sprint2的每日更新
按照以下过程进行 ProductBacklog:继续向下细化 Sprint 计划会议:确定此次冲刺要完成的目标 Sprint Backlog:新的冲刺要完成的内容 任务认领 Sprint周期 看板:一 ...
- appium启动sdk的android模拟器
(1)启动sdk安装目录下的AVD Manager.exe (2)如下图,点击[create]按钮 (3)如下图,设置虚拟机的配置,至于Target中的:Android 4.4.2是在安装sdk的时候 ...
- Java 文件下载功能 解决中文乱码
Html部分 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...