day04Go复习和刷题 | 青训营日记

41 阅读3分钟

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知识逐渐生疏了。

最近准备捡起来刷题习惯.

611. 有效三角形的个数 - 力扣(LeetCode)

56. 合并区间 - 力扣(LeetCode)

209. 长度最小的子数组 - 力扣(LeetCode)