当前位置:网站首页>2021-09-04 最简单的Golang定时器应用以及最简单的协程入门儿
2021-09-04 最简单的Golang定时器应用以及最简单的协程入门儿
2022-08-02 03:26:00 【rockage】
- 什么是协程,作用是什么?
协程是Go语言实现并发处理的一种方式,说成人话就是在一个程序里同时跑两段代码。比如一个普通的函数 func abc() ,当我们执行abc()的时候,主程序会一直等待abc执行完毕之后再继续,这就是所谓的“阻塞”。很显然,程序是以“串行”方式执行的,效率不高。而如果采用协程的话,则只需要在函数名前面加上 go 这个关键字:go func abc() , 这时候,系统将开辟一个新的空间给函数abc去运行,而不会一直等待它执行完毕,也就是说主程序和函数abc是同时运行的,因此也就实现了“并行”的目的。 这时候,主程序和协程之间就不再是通过传统的传参方式去交互变量了。而是通过一种叫做 “通道” 的东西进行交流。 - ch := make(chan bool) 是什么意思?
表示创建一个名为ch的通道,通道中传递的数据类型是布尔型,当然,通道可以传递任意类型,包括自定义类型。譬如说,如果需要在通道中传递字符串类型则:ch := make(chan string)
chan 是Go语言的一种特殊的数据类型,是英文 channel (通道)的缩写,比如以下这条指令:v := <-ch
表示:获取ch 通道的变量并存在v里,注意:通道本身并不是变量的值,但是变量的值可以通过通道传递,通道的一头接主程序,另一头接协程。比如在主程序这边我们输入:ch <- true
意思是说将true这个值发送到通道channel,
然后在协程这边,我们通过:v := <-ch
从通道中接收从主程序传输过来的值,此时的v就是true. - select case是什么?
用于管理不同的通道,简单地说就是当不同的通道出现新的内容后,该如何处理他们。 - ticker.C 是什么鬼?
就是当前时间,Go定时器在time.NewTicker的时候自动产生了一条通道,按照指定的时间间隔(比如500毫秒)向这条通道发送当前时间(如果你把它打印出来,就是一个当前时间值),如果我们的业务需求并不关注当前时间,可以忽略这个值。可以仅仅看作是一条 “ 时间到了 ” 的信号即可。 - 为什么会出现两个for {} 死循环?
第一个for {} 死循环出现在协程内部,因为协程开启之后就跟主程序无关了,正常情况下协程执行完毕后return就回来了,但显然定时器这种场合是需要一直保持运转的,因此我们看到在协程内部有一个for {} 死循环,这个循环通过select case{} 持续扫描 channel 通道和ticker.C通道的变化,当通道ticker.C发生变化时,执行我们预先指定好的函数,当channel 通道发生变化时,关闭定时器,退出协程。
第二个出现在main主函数里面的for {} 死循环就更容易理解了,它让主程序可以持续运行,否则程序一闪而过,那就没法测试了。
package main
import (
"fmt"
"time"
)
type Timer struct {
Interval int // 设置时间间隔
Tick func() // 时间到了调用哪个程序?
Channel chan bool // 用以和主程序交互的通道
}
// 协程部分:
func (t Timer) Enabled() {
ticker := time.NewTicker(time.Duration(t.Interval) * time.Millisecond)
// 生成一个ticker,到了Intervar指定时间,就执行Tick() ,单位是毫秒
go func() {
// 开启一个协程
for {
// 协程内是死循环,除非检测到channel通道有内容才会退出
select {
case <-t.Channel: // 检测到来自channel通道有内容,不管内容是什么,直接停止ticker
ticker.Stop()
return
case <-ticker.C: // .C 是ticker内置的一个成员,将当前时间送入ticker通道
t.Tick() // 检测到ticker通道有内容后,执行Tick()函数
}
}
}() // 后面这个(),表示立即执行的意思
}
// 主程序部分:
func main() {
// 用法如下:
tick1 := func() {
// 首先定义两个定时器到时间后需要执行的函数:tick1 和 tick2
fmt.Print(" A ")
}
tick2 := func() {
fmt.Print(" B ")
}
timer1 := new(Timer)
timer1.Interval = 500 // 定时器1:每500ms触发一次
timer1.Tick = tick1 // 时间到,调用tick1函数
timer1.Channel = make(chan bool) // 创建一条通道
timer1.Enabled() // 启动定时器1
timer2 := new(Timer)
timer2.Interval = 1000
timer2.Tick = tick2
timer2.Channel = make(chan bool)
timer2.Enabled()
// main循环(死)
for {
var cmds string
fmt.Scanln(&cmds) // 检测用户输入
if cmds == "1" {
timer1.Channel <- false // 关闭定时器1并退出协程
// 注意: 其实此处无论是true还是false都一样,关键是将值
// 送入通道,而并不关心值到底是多少。
}
if cmds == "2" {
timer2.Channel <- true // 用true效果一样
}
}
}
- 以上代码实现的功能:
- 产生两个独立的定时器,timer1 间隔时间为500ms, timer2间隔时间为1000ms。
- 屏幕上以1秒为一个周期显示字符“A”, 以两秒一个周期显示“B”
- 在主界面输入字符“1”,则停止timer1,输入2则停止timer2。
- 后记
我感觉注释已经说得很清楚了,如果你对Go协程有点了解的话,上面的代码还是很简单的。关于Golang协程的概念还有很多内容,门道还是有点杂的,本文只起一个最简单的抛砖引玉的作用。
边栏推荐
- CTF introductory notes ping
- 政府会计的概念、政府会计标准体系、政府会计的特点(会形成小考点)、政府会计要素及其确认和计量、政府预算会计要素、政府财务会计要素
- 什么是广告电商商业模式?这几个门派告诉你
- VIKINGS: 1 vulnhub walkthrough
- Alfa: 1 vulnhub walkthrough
- GreenOptic: 1 vulnhub walkthrough
- 借贷记账法下的账户结构、借贷记账法的记账规则、借贷记账法下的账户对应关系与会计分录
- 12. What is JS
- Several interesting ways to open PHP: from basic to perverted
- Shuriken: 1 vulnhub walkthrough
猜你喜欢
redis未授权访问(4-unacc)
How to determine the direction based on two coordinate points on the map
Eric靶机渗透测试通关全教程
How to calculate the distance between two points on the earth (with formula derivation)
Several interesting ways to open PHP: from basic to perverted
VIKINGS: 1 vulnhub walkthrough
GreenOptic: 1 vulnhub walkthrough
账务处理程序、记账凭证账务处理程序、汇总记账凭证账务处理程序、科目汇总表账务处理程序、会计信息化概述、信息化环境下会计账务处理的基本要求(此章出1道小题)
PHP反序列化漏洞
PHP deserialization vulnerability
随机推荐
hackmyvm-bunny预排
Pycharm打包项目为exe文件
Solve the problem of Zlibrary stuck/can't find the domain name/reached the limit, the latest address of Zlibrary
17. JS conditional statements and loops, and data type conversion
cmake安装到指定目录
How to determine the direction based on two coordinate points on the map
元宇宙:为何互联网大佬纷纷涉足?元宇宙跟NFT是什么关系?
一个网络安全小白鼠的学习之路——nmap的基本使用
(3) string
元宇宙是一个炒作的科幻概念,还是互联网发展的下半场?
16. JS events, string and operator
CSRF (Cross Site Request Forgery)
Anaconda报错:An unexpected error has occurred. Conda has prepared the above report 解决办法
战场:3(双子叶植物)vulnhub走读
file contains vulnerabilities
Praying: 1 vulnhub walkthrough
[campo/random-user-agent] Randomly fake your User-Agent
The first time to tear the code by hand, how to solve the problem of full arrangement
(5) Modules and packages, encoding formats, file operations, directory operations
对账、结账、错账更正方法、划线更正法、红字更正法、补充登记法