Go语言实战--学习笔记--runner
Go语言实战–runner
代码
runner.go
// Example is provided with help by Gabriel Aszalos.
// Package runner manages the running and lifetime of a process.
package runnerimport ("errors""os""os/signal""time"
)// Runner runs a set of tasks within a given timeout and can be
// shut down on an operating system interrupt.
type Runner struct {// interrupt channel reports a signal from the// operating system.interrupt chan os.Signal// complete channel reports that processing is done.complete chan error// timeout reports that time has run out.timeout <-chan time.Time// tasks holds a set of functions that are executed// synchronously in index order.tasks []func(int)
}// ErrTimeout is returned when a value is received on the timeout channel.
var ErrTimeout = errors.New("received timeout")// ErrInterrupt is returned when an event from the OS is received.
var ErrInterrupt = errors.New("received interrupt")// New returns a new ready-to-use Runner.
func New(d time.Duration) *Runner {return &Runner{interrupt: make(chan os.Signal, 1),complete: make(chan error),timeout: time.After(d),}
}// Add attaches tasks to the Runner. A task is a function that
// takes an int ID.
func (r *Runner) Add(tasks ...func(int)) {r.tasks = append(r.tasks, tasks...)
}// Start runs all tasks and monitors channel events.
func (r *Runner) Start() error {// We want to receive all interrupt based signals.signal.Notify(r.interrupt, os.Interrupt)// Run the different tasks on a different goroutine.go func() {r.complete <- r.run()}()select {// Signaled when processing is done.case err := <-r.complete:return err// Signaled when we run out of time.case <-r.timeout:return ErrTimeout}
}// run executes each registered task.
func (r *Runner) run() error {for id, task := range r.tasks {// Check for an interrupt signal from the OS.if r.gotInterrupt() {return ErrInterrupt}// Execute the registered task.task(id)}return nil
}// gotInterrupt verifies if the interrupt signal has been issued.
func (r *Runner) gotInterrupt() bool {select {// Signaled when an interrupt event is sent.case <-r.interrupt:// Stop receiving any further signals.signal.Stop(r.interrupt)return true// Continue running as normal.default:return false}
}
main.go
// This sample program demonstrates how to use a channel to
// monitor the amount of time the program is running and terminate
// the program if it runs too long.
package mainimport ("log""os""time""github.com/goinaction/code/chapter7/patterns/runner"
)// timeout is the number of second the program has to finish.
const timeout = 3 * time.Second// main is the entry point for the program.
func main() {log.Println("Starting work.")// Create a new timer value for this run.r := runner.New(timeout)// Add the tasks to be run.r.Add(createTask(), createTask(), createTask())// Run the tasks and handle the result.if err := r.Start(); err != nil {switch err {case runner.ErrTimeout:log.Println("Terminating due to timeout.")os.Exit(1)case runner.ErrInterrupt:log.Println("Terminating due to interrupt.")os.Exit(2)}}log.Println("Process ended.")
}// createTask returns an example task that sleeps for the specified
// number of seconds based on the id.
func createTask() func(int) {return func(id int) {log.Printf("Processor - Task #%d.", id)time.Sleep(time.Duration(id) * time.Second)}
}
代码分析
runner包:
使用通道监视程序的执行时间,当程序运行时间太长时,可以使用runner包中止程序。
type Runner struct {interrupt chan os.Signalcomplete chan errortimeout <-chan time.Timetasks []func(int)
}
Runner结构体:
定义了
1 通过channel接收来自操作系统发送的信号
2 任务完成的信号
3 超时信号
4 任务切片
New
func New(d time.Duration) *Runner {return &Runner{interrupt: make(chan os.Signal, 1),complete: make(chan error),timeout: time.After(d),}
}
通过New返回一个新的Runner:
complete:
当执行任务的goroutine完成时,会向这个通道发送一个error类型的值或者nil值。之后就会等待main函数接收这个值。一旦main接收了这个error值,goroutine就可以安全地终止了
time.After(d):
func After(d Duration) <-chan Time {return NewTimer(d).C
}
Add
func (r *Runner) Add(tasks ...func(int)) {r.tasks = append(r.tasks, tasks...)
}
Add方法,这个方法接收一个名为 tasks 的可变参数。可变参数可以接受任意数量的值作为传入参数。这个例子里,这些传入的值必须是一个接收一个整数且什么都不返回的函数。函数执行时的 参数tasks是一个存储所有这些传入函数值的切片
run
func (r *Runner) run() error {for id, task := range r.tasks {if r.gotInterrupt() {return ErrInterrupt}task(id)}return nil
}
检查操作系统有无中断信号,没有则继续执行
gotInterrupt
func (r *Runner) gotInterrupt() bool {select {case <-r.interrupt:signal.Stop(r.interrupt)return truedefault:return false}
}
其中signal.Stop(r.interrupt):
func Stop(c chan<- os.Signal)
Stop函数让signal包停止向c转发信号。它会取消之前使用c调用的所有Notify的效果。当Stop返回后,会保证c不再接收到任何信号。
start
func (r *Runner) Start() error {signal.Notify(r.interrupt, os.Interrupt)go func() {r.complete <- r.run()}()select {case err := <-r.complete:return errcase <-r.timeout:return ErrTimeout}
}
实现了程序的主流程:
func Notify(c chan<- os.Signal, sig ...os.Signal)
Notify函数让signal包将输入信号转发到c。如果没有列出要传递的信号,会将所有输入信号传递到c;否则只传递列出的输入信号。
signal包不会为了向c发送信息而阻塞(就是说如果发送时c阻塞了,signal包会直接放弃):调用者应该保证c有足够的缓存空间可以跟上期望的信号频率。对使用单一信号用于通知的通道,缓存为1就足够了。
main.go
r.Add(createTask(), createTask(), createTask())
func createTask() func(int) {return func(id int) {log.Printf("Processor - Task #%d.", id)time.Sleep(time.Duration(id) * time.Second)}
}
Go语言实战--学习笔记--runner相关推荐
- R语言实战学习笔记-高级数据管理
本文将从以下几个方面介绍R语言中的数据管理,1.数据处理函数 2.控制流 3.用户自定义函数 4.整合和重构 1.数据的处理函数 #实例 x<-c(1,2,3,4,5,6,7,8,9) y< ...
- “物联网开发实战”学习笔记-(四)智能音箱制作和语音控制
"物联网开发实战"学习笔记-(四)智能音箱制作和语音控制 这次来造一个属于自己的智能音箱,这里详细介绍了智能音箱的语音控制的实现. 智能音箱的技术架构 智能音箱主要涉及拾音.前端信 ...
- R语言可视化学习笔记之相关矩阵可视化包ggcorrplot
本文转载自"R语言中文社区",己获授权. 作者简介Introduction taoyan:伪码农,R语言爱好者,爱开源. 个人博客: https://ytlogos.github. ...
- R语言可视化学习笔记之ggridges包绘制山峦图
作者:严涛 浙江大学作物遗传育种在读研究生(生物信息学方向)伪码农,R语言爱好者,爱开源. 严涛老师的绘图教程还有: gganimate |诺奖文章里面的动图绘制教程来了!! ggplot2学习笔记之 ...
- Java 8 实战学习笔记
Java 8 实战学习笔记 @(JAVASE)[java8, 实战, lambda] 文章目录 Java 8 实战学习笔记 参考内容 Lambda表达式 Lambda环绕执行模式(抽离步骤) 原始代码 ...
- Linux性能优化实战学习笔记:第四十六讲=====实战分析
Linux性能优化实战学习笔记:第四十六讲 一.上节回顾 不知不觉,我们已经学完了整个专栏的四大基础模块,即 CPU.内存.文件系统和磁盘 I/O.以及网络的性能分析和优化.相信你已经掌握了这些基础模 ...
- “物联网开发实战”学习笔记-(五)根据土壤湿度、环境温湿度和光照强度自动浇花
"物联网开发实战"学习笔记-(五)根据土壤湿度.环境温湿度和光照强度自动浇花 研究场景需求 自动浇花这个场景,很明显是为了自动控制水泵,及时给植物补充水分.同时用户的目的并不只是浇 ...
- Go语言实战读书笔记
2019独角兽企业重金招聘Python工程师标准>>> Go语言实战读书笔记 第二章 通道(channel).映射(map)和切片(slice)是引用类型.引用类型的对象需要使用ma ...
- c语言课程笔记格式,C语言课程学习笔记.docx
C语言课程学习笔记 C语言基础语言排行榜C--java--objective-C进制:进制:进位机制.用普通的话讲,应该为人为的定义一种度量来标识一样东西.计算机常用的进制有:十进制.二进制.八进制和 ...
- r语言electricity数据集_R语言实战学习
<R语言实战>中文电子版 提取码:lx35 已经学习打卡R语言22天了,可以说是初窥真容--基本了解R的数据和函数:作为程序语言,就是要多练习,多领悟,在实战中发现问题并解决问题. 所以, ...
最新文章
- 计算机病毒洛,蓝狐动漫《百变机兽》中未完的战争,蓝毒兽原来是电脑病毒?...
- java空指针避坑指南
- 如何用智能有效感知城市?城市大脑三大AI产品来了
- kafka学习汇总系列(一)kafka概述
- 没人性!让我们这么早来上班
- 用计算机制作动画,如何使用制作工具制作一个简单的Flash动画-电脑自学网
- python随机选人程序_python: 随机选择
- 新浪邮箱文件下载php,免费邮箱大全收集-国内篇
- 桥接模式 和 中继模式
- lvds输入悬空_低压差分信号LVDS学习笔记-模拟/电源-与非网
- CentOS 7 systemd添加自定义系统服务
- Git reset --hard commit_id 和 git reset --soft commit_id
- Qt实现word文档转html
- AI发展的桎梏在于理解能力?大咖开出的十一条建议「AI前沿」
- oracle(知识点速查)
- 与或非门——python逻辑电路
- 移动端实时音视频直播技术详解(一):开篇
- 基于springboot的工资管理系统
- 洛谷 P1319 压缩技术 C/C++
- libs与External Libraries