这是我参与「第五届青训营 」伴学笔记创作活动的第2天。
一、并发编程与依赖管理
协程与线程
解决并发问题,我们常用线程来并行地运行多个程序,但这种内核态的解决方案会占用mb级别的内存调用。轻量级的协程仅占用kb级别的内存,在一个线程中,可以调度多个协程。
Goroutine
Goroutine是Go语言提供的协程,与kotlin中的无栈协程不同,是一种有栈协程。如下代码是一个简单的goroutine的使用例子:
package main
import (
"fmt"
"time"
)
func print(i int) {
fmt.Println(i)
}
func main() {
for i := 1; i <= 10; i++ {
go func(j int) {
print(j)
}(i)
}
time.Sleep(time.Second)
}
其输出结果为:
1
2
6
4
8
5
7
9
3
如果删去 time.Sleep(time.Second)程序将不会有任何输出。原因是当主协程退出后,其中的子协程会立即结束。由于变量的自增执行速度快于打印数字,当main协程结束时,子协程还没来得及打印就被结束了。我们用time.Sleep(time.Second)方法来延迟主协程的结束,这种方法存在一个问题:人为的设定时间并不一定与协程执行时间匹配,可能出现子协程执行完毕,主协程仍然无法结束的问题。Go语言提供了更科学的解决方案:Waitgroup。简单来说waitgroup维护着一个计数器,程序员们可以通过调用Add()方法设定初始值,Done()方法来使计数器-1,wait()方法来使协程阻塞直至计数器为0。这样,我们就能较好的解决主/子协程运行时间不匹配的问题了。
依赖管理
经过不断更迭,go的依赖管理从GOPATH,GoVender,演化为如今的GoModule。GoModule较好地解决了前身的不同项目依赖的同一项目的不同版本问题。Gomodule会评估不同项目的依赖,并且选择能够兼容这些项目的最低版本作为依赖。
小结
今天对go语言的特点,乃至项目方面的依赖管理有了一定的了解。初次接触这些,感觉猪脑有点过载了~