第二十一篇:go协程练习:sync包入门、等待协程执行结束
一:上节课代码

上节课代码逻辑是:通过协程来抓取,抓取完成以后使用主线程来执行写入,如果抓取和写入放到一个协程里就不需要管道来通信了,
怎么来判断我们协程全部执行完成了?我们接下来来了解sync这个包
二:sync包
sync中文意思是:同步。后面我们还会用到此包
其中sync包有个很有用的功能WaitGroup ,一共有3个方法
Add(参数 int)、done()、wait()
内部创建一个计数器,使用
1、Add 用来添加 goroutine 的个数
2、Done 执行一次数量减 1, 好比Add(-1)
3、Wait 用来阻塞主线程,直到所有协程执行完毕 (好比其他语言中的join())
我们在执行多个协程的时候,为了能判断出它们在执行完成我们在主线程里面执行wait用来阻塞主线程,直到所有协程执行完毕之后才能继续往下继续执行

测试代码:

三:获取协程数
runtime包,运行时系统交互操作,例如控制 goroutines 的函数。其中比较有用的几个方法
Gosched:让当前goroutine让出 cpu 以让其它goroutine运行,它不会挂起当前goroutine,
NumCPU:返回当前系统的 CPU 核数
GOMAXPROCS:设置最大的可同时使用的 CPU 核数
Goexit:退出当前 goroutine(但是defer语句会照常执行)
NumGoroutine:返回正在执行和排队的任务总数

利用sync包将 写入操作放在抓取的协程里执行

课外补充:defer
defer概述
defer语句是Go中一个非常有用的特性,可以将一个方法延迟到包裹该方法的方法返回时执行,在实际应用中,defer语句可以充当其他语言中try…catch…的角色,也可以用来处理关闭文件句柄等收尾操作。
defer触发时机
Go官方文档中对defer的执行时机做了阐述,分别是。
包裹defer的函数返回时
包裹defer的函数执行到末尾时
所在的goroutine发生panic时
(1) :defer表达式中变量的值在defer表达式被定义时就已经明确
func a() {
i := 0
defer fmt.Println(i)
i++
return
}
所以,程序运行结束的时候,输出的结果是0而不是1。
(2) defer表达式的调用顺序是按照先进后出的方式
(3) defer表达式中可以修改函数中的命名返回值
func c() (i int) {
defer func() { i++ }()
return 1
}
返回值变量名为i,在defer表达式中可以修改这个变量的值。所以,虽然在return的时候给返回值赋值为1,后来defer修改了这个值,让i自增了1,所以,函数的返回值是2而不是1。

浙公网安备 33010602011771号