Bruce Blog Bruce Blog
首页
  • CentOS
  • Ubuntu-Debian
  • 系统网络
  • 系统辅助工具
  • MySQL
  • Redis
  • Mongodb
  • Docker基础
  • Container基础
  • Kubernetes

    • Kubernetes基础
    • Kubernetes辅助
  • Container-Network
  • Jenkins
  • Gitlab
  • ArgoCD
  • Ansible
  • Terraform
  • AWS
  • MQ
  • NGINX
  • JumpServer
  • 基础
  • 函数模块
  • 框架
  • 基础

    • Golang环境
    • 语法
    • 数据类型与运算符
    • 分支语句
    • 循环语句
    • 数组
    • 切片
    • Map
    • String
    • 函数
    • 包的管理
    • 指针
    • 结构体
    • Go语言中的OOP
    • 方法和接口
    • 错误处理
  • Go进阶

    • Go进阶
  • Go框架

    • Go框架
  • Golang辅助

    • Golang辅助
  • CSS
  • HTML
  • JavaScript
  • 前端辅助
  • 常用命令
  • 性能监控工具
  • Windows下Docker使用
  • 日常学习
  • 其他导航

Bruce Tao

运维界的该溜子
首页
  • CentOS
  • Ubuntu-Debian
  • 系统网络
  • 系统辅助工具
  • MySQL
  • Redis
  • Mongodb
  • Docker基础
  • Container基础
  • Kubernetes

    • Kubernetes基础
    • Kubernetes辅助
  • Container-Network
  • Jenkins
  • Gitlab
  • ArgoCD
  • Ansible
  • Terraform
  • AWS
  • MQ
  • NGINX
  • JumpServer
  • 基础
  • 函数模块
  • 框架
  • 基础

    • Golang环境
    • 语法
    • 数据类型与运算符
    • 分支语句
    • 循环语句
    • 数组
    • 切片
    • Map
    • String
    • 函数
    • 包的管理
    • 指针
    • 结构体
    • Go语言中的OOP
    • 方法和接口
    • 错误处理
  • Go进阶

    • Go进阶
  • Go框架

    • Go框架
  • Golang辅助

    • Golang辅助
  • CSS
  • HTML
  • JavaScript
  • 前端辅助
  • 常用命令
  • 性能监控工具
  • Windows下Docker使用
  • 日常学习
  • 其他导航
  • 基础

  • Go进阶

    • Go进阶
    • File操作
    • IO操作
    • 文件复制
    • 断点续传
    • bufio包
    • ioutil包
    • 遍历目录
    • 并发性Concurrency概念
    • Goroutine初识
    • Goroutine并发模型
    • Runtime包
    • 临界资源安全问题
    • sync包WaitGroup
    • 互斥锁
    • 读写锁
    • Channel通道
    • 关闭通道和通道上范围循环
    • 缓冲通道
    • 定向通道
    • time包中的通道相关函数
      • select语句
      • CSP并发模型
      • Go语言反射(一)
      • Go语言反射(二)
    • Go框架

    • Golang辅助

    • Golang
    • Go进阶
    Bruce
    2022-12-03
    目录

    time包中的通道相关函数

    # time包中的通道相关函数

    • https://golang.google.cn/pkg/time/

    主要就是定时器,标准库中的Timer让用户可以定义自己的超时逻辑,尤其是在应对select处理多个channel的超时、单channel读写的超时等情形时尤为方便.

    Timer是一次性的时间触发事件,这点与Ticker不同,Ticker是按一定时间间隔持续触发时间事件.

    Timer常见的创建方式

    t: = time.NewTimer(d)
    t: = time.AfterFunc(d,f)
    c: = time.After(d)
    
    1
    2
    3

    虽然说创建方式不同,但是原理相同的.

    Timmer有3个要素

    定时时间: 就是那个d

    触发动作: 就是那个f

    时间channel: 也就是t.C

    # 一、time.NewTimer()

    NewTimer()创建一个新的计时器,该计时器将在其通道上至少持续d之后发送当前时间.

    image-20221125115815316

    image-20221125120531377

    NewTimer源码

    // NewTimer creates a new Timer that will send
    // the current time on its channel after at least duration d.
    func NewTimer(d Duration) *Timer {
    	c := make(chan Time, 1)
    	t := &Timer{
    		C: c,
    		r: runtimeTimer{
    			when: when(d),
    			f:    sendTime,
    			arg:  c,
    		},
    	}
    	startTimer(&t.r)
    	return t
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    通过源码可以看出,首先创建一个channel,关联的类型为Time,然后创建了一个Timer并返回

    • 用于在指定的Duration类型时间后调用函数或计算表达式.
    • 如果只是想指定时间之后执行,使用time.Sleep()
    • 使用NewTimer(),可以返回的Timer类型在计时器到期之前,取消该计时器
    • 直到使用<-timer.C发送一个值,该计时器才会过期.

    示例代码

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	/*
    		1.func NewTimer(d Duration) *Timer
    			创建一个计时器,时间以后触发
    	*/
    
    	timer := time.NewTimer(3 * time.Second)
    	fmt.Printf("%T\n", timer) //*time.Timer
    	fmt.Println(time.Now())   // 2022-11-25 12:06:50.9444009 +0800 CST m=+0.002697901
    	
    	//此处等待`channel`中的数值,会阻塞3秒
    	ch1 := timer.C
    	fmt.Println(<-ch1) // 2022-11-25 12:06:53.9565868 +0800 CST m=+3.014883801
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    执行结果

    image-20221125121303559

    # 二、timer.Stop

    # 计时器停止

    image-20221125123813475

    timer.Stop源码

    // Stop prevents the Timer from firing.
    // It returns true if the call stops the timer, false if the timer has already
    // expired or been stopped.
    // Stop does not close the channel, to prevent a read from the channel succeeding
    // incorrectly.
    //
    // To ensure the channel is empty after a call to Stop, check the
    // return value and drain the channel.
    // For example, assuming the program has not received from t.C already:
    //
    // 	if !t.Stop() {
    // 		<-t.C
    // 	}
    //
    // This cannot be done concurrent to other receives from the Timer's
    // channel or other calls to the Timer's Stop method.
    //
    // For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer
    // has already expired and the function f has been started in its own goroutine;
    // Stop does not wait for f to complete before returning.
    // If the caller needs to know whether f is completed, it must coordinate
    // with f explicitly.
    func (t *Timer) Stop() bool {
    	if t.r.f == nil {
    		panic("time: Stop called on uninitialized Timer")
    	}
    	return stopTimer(&t.r)
    }
    
    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
    26
    27
    28

    示例代码

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	/*
    		1.func NewTimer(d Duration) *Timer
    			创建一个计时器,时间以后触发
    	*/
    
    	//新建一个计时器
    	timer2 := time.NewTimer(5 * time.Second)
    	//开始`goroutine`,来处理触发后的事件
    	go func() {
    		<-timer2.C
    		fmt.Println("Timer 2 结束了...开始...")
    	}()
    
    	time.Sleep(3 * time.Second)
    	flag := timer2.Stop()
    	if flag {
    		fmt.Println("Timer2 停止了...")
    	}
    }
    
    
    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
    26
    27
    28

    执行结果

    image-20221125121426688

    # 三、time.After()

    在等待持续时间之后,然后在返回的通道上发送当前时间.它相当NewTimer(d).C.在计时器触发之前,垃圾收集器不会恢复底层计时器,如果效率有问题,使用NewTimer代替,并调用Timer.如果不再需要计时器,请停止.

    image-20221125124924851

    源码

    // After waits for the duration to elapse and then sends the current time
    // on the returned channel.
    // It is equivalent to NewTimer(d).C.
    // The underlying Timer is not recovered by the garbage collector
    // until the timer fires. If efficiency is a concern, use NewTimer
    // instead and call Timer.Stop if the timer is no longer needed.
    func After(d Duration) <-chan Time {
    	return NewTimer(d).C
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    示例代码

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	/*
    		2.func After(d Duration) <-chan Time
    			返回一个通道: chan,存储的是d时间间隔之后的当前时间
    
    		相当于: return NewTimer(d).C
    	*/
    	ch := time.After(3 * time.Second)
    	fmt.Printf("%T\n", ch) // <-chan time.Time
    	fmt.Println(time.Now())
    
    	time1 := <-ch
    	fmt.Println(time1)
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    执行结果

    image-20221125130125803

    上次更新: 2024/04/09, 16:48:42
    定向通道
    select语句

    ← 定向通道 select语句→

    最近更新
    01
    AWS NAT-NetWork-Firwalld配置(一)
    04-09
    02
    AWS NAT-NetWork-Firwalld配置(二)
    04-09
    03
    kubernetes部署minio对象存储
    01-18
    更多文章>
    Theme by Vdoing | Copyright © 2019-2024 Bruce Tao Blog Space | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式