go复习
复习了前几天Go基础,重点看了下多并发协程使用。
并不是必须使用多进程或多线程才可以实现高并发,很多时候,特别是web相关应用,当你读取文件或者调用API都会产生IO,但是由于计算机硬盘、网络传输速度比较慢,CPU就会一直在那等...时间就浪费了!后来有人想,既然在等IO,你就把CPU让出来让其它人用啊,当硬盘数据读取到、接口返回数据的时候我通知你一声就行了,=
在我理解,go的协程是为了解决多核CPU利用率问题,go语言层面并不支持多进程或多线程,但是协程更好用,协程被称为用户态线程,不存在CPU上下文切换问题,效率非常高。
WaitGroup
package main
import (
"sync"
)
var wg = sync.WaitGroup{}
func main() {
wg.Add(1)
go say("Hello World")
wg.Wait()
}
func say(s string) {
println(s)
wg.Done()
}
开始可以使用主线程睡眠的方式,但是不能准确的控制睡眠的时间。使用WaitGroup就可以更加优雅的使用携程。
var 是声明了一个全局变量 wg,类型是sync.WaitGroup,wg.add(1) 是说我有1个协程需要执行,wg.Done 相当于 wg.Add(-1) 意思就是我这个协程执行完了。wg.Wait() 就是告诉主线程要等一下,等协程都执行完再退出.
hannel
channel,又叫管道,在go里面的管道是协程之间通信的渠道,类似于咱们常用的消息队列。在上面的例子里面我们是直接打印出来结果,假如现在的需求是把输出结果返回到主线程呢?
package main
import (
"strconv"
)
func main() {
var result = make(chan string)
for i := 0; i < 5; i++ {
go say("Hello World: "+strconv.Itoa(i), result)
}
for s := range result {
println(s)
}
}
func say(s string, c chan string) {
c <- s
}
这里就是实例化了一个string类型的管道,在调用函数的时候会把管道当作参数传递过去,然后在调用函数里面我们不输出结果,然后把结果通过管道返还回去,然后再主线程里面我们通过for range循环依次取出结果!
Hello World: 0
Hello World: 2
Hello World: 3
Hello World: 1
Hello World: 4
fatal error: all goroutines are asleep - deadlock!
go的管道默认是阻塞的(假如你不设置缓存的话),你那边放一个,我这头才能取一个,如果你那边放了东西这边没人取,程序就会一直等下去,死锁了,同时,如果那边没人放东西,你这边取也取不到,也会发生死锁!
如何解决这个问题呢?标准的做法是主动关闭管道,使用close关闭。
今日刷题
研一上一直在忙于课程的quiz和homework,期末的一段时间又在做project,Java知识逐渐生疏了。
最近准备捡起来刷题习惯.