Go语言进阶overview
内容:Go的并发简介,依赖管理演进与比较,版本与module路径。
并发与并行
并发是指多个线程在同一cpu上进行处理;
并行是指多个线程在多个cpu上处理;
Go与高并发
Go语言拥有goroutine,天然高并发;
goroutine是比线程更小的单位,你可以理解为用户态的协程,而线程为内存态;
具体大小方面,协程为栈KB级别,线程为栈MB级别;
CSP
通过通讯共享内存
前面说过,goroutine是Go语言天然高并发的优势所在,而不同的goroutine之间必然要有数据的交流,这种数据交流在Go中需要用csp的思想来实现,落实到具体,用了channel这一数据类型,它就像一个管道,在不同的goroutine之间起到了通讯的作用。
之所以采取CSP,是因为其能达到以下几个效果:
1.避免多个goroutine同时修改某一变量导致的竞态条件;
2.易于理解,维护代码;
3.提高了并发性能;
原先,需要加锁,解锁以保障安全,现在省去了这些步骤,性能得到提高;
锁
前面讲CSP时讲到一种情况,多个goroutine同时修改某一个变量,会引起竞态条件,导致结果不可预料,我们可以采取锁的方式来解决;
var (
x int64
lock sync.Mutex
)
func addFunc() {
lock.Lock()
defer lock.Unlock()
x++
}
依赖管理
-
Go依赖版本的演进之路:
GOPATH—VENDER—GOMODULE
值得注意的是,module推出后,在可访问公网环境下,已经不需要vender这个文件夹了,但是GOPATH依旧保存下来,module只是替代了它的包管理功能,GOPATH依旧持有存放包,存放可执行文件等功能。
-
GOPATH三大文件夹: bin : 存放二进制文件
pkg: 存放项目编译的中间产物,便于加速
src: 存放包的源码
三大时代的比较:
GOPATH时代,由于所有依赖的包均放在同一文件夹下,我们无法处理多版本包的问题;
Vender时代,为每一个项目引入依赖的副本,当需要新版本时,无法方便的更新,同时容易引起依赖冲突问题;
Module时代,通过go.mod文件,go get,GOPROXY这三个核心,我们可以解决依赖问题,
我们可以使用go mod init来初始化项目,当我们需要添加依赖包时,只需使用go get modulepath,就可以快速获得依赖包;
注意:在项目严格遵循语义化版本的前提下,假设当前版本为v2.13.2,那么同一主版本下的不同次版本还有补包都是共享同一个module引入路径,不同主版本号(如 v1.13.2, v3.4.0)有不同的引入路径。