这是我参与「第五届青训营 」伴学笔记创作活动的第 10 天
并发安全锁
package main
import (
"sync"
"time"
)
var (
x int64
lock sync.Mutex
)
func addWithLock() {
for i := 0; i < 2000; i++ {
lock.Lock()
x += 1
lock.Unlock()
}
}
func addWithoutLock() {
for i := 0; i < 2000; i++ {
x += 1
}
}
func Add() {
x = 0
for i := 0; i < 5; i++ {
go addWithoutLock()
}
time.Sleep(time.Second)
println("WithoutLock:", x)
x = 0
for i := 0; i < 5; i++ {
go addWithLock()
}
time.Sleep(time.Second)
println("WithLock:", x)
}
func main() {
Add()
}
可以发现使用锁和不使用锁得到结果不同,不使用锁得到的结果不是我们预期想要的。.
依赖管理
对于hello world以及类似的单体函数只需要依赖原生SDK,而实际工程会相对复杂,我们不可能仅仅依赖标准库的代码去搭建。
实际的工程中我们更多关注业务逻辑的实现,而其他的一系列依赖都会通过sdk的方式引入,这样就对依赖包的管理就十分重要。
GOPATH 模式
从 Go 1.8 版本开始,安装 Go 开发包时会默认为 GOPATH 变量设置一个目录路径,它表示的是 Go 语言的工作目录,这个目录下会有三个子目录,它们分别是:
- bin:存放编译后生成的二进制可执行文件
- pkg:存放编译后生成的 .a文件
- src:存放项目的源代码,有自己写的代码,还有通过 go get命令下载的包
GoPath 模式的弊端
在 Go 1.11版本之前,开发者是必须要配置 这个GOPATH环境变量的,这种代码代码管理模式存在比较严重的问题就是没有版本控制。
因为多个项目都会放在src目录下,而每个项目依赖的一些第三方包也是下载在src目录下的,当升级某个依赖包时就是全局升级,引用这个依赖包的项目都跟着升级包的版本了,这样是一件很危险的事,因为你不知道升级的包在另外一个项目中是否能正常运行。而且当多人协同开发时,你不知道别人下载的包是不是你所用的那个版本,容易出错且不好排查原因。
GO Vendor模式
在每个项目下都创建一个 vendor 目录,每个项目所需的依赖都只会下载到自己vendor目录下,项目之间的依赖包就互不影响了。在使用包时,会先从当前项目下的 vendor 目录查找,然后依次向上级目录查找。这种方式依旧是 GOPATH 模式下的,它解决了不同项目不能使用不同版本库的问题。
GO Vendor模式的弊端
- 无法控制依赖的版本
- 更新项目有可能出现依赖冲突,导致编译出错
Go Module模式
GoModules 模式是 Go 语言 1.11 版本正式推出的,在 1.14 版本时,官方就发话 GoModules 的模拟已经成熟,可以用于生产环境,在1.16版本后默认开启的模式。
通过go.mod文件管理依赖的版本
通过go get/go mod指令工具管理依赖包
工程不用全放在go path/src目录下
特点:
GO MODULE模式下所有依赖的包存放在$GOPATH/pkg/mod目录下
项目中需要有go.mod文件,来应用$GOPATH/pkg/mod
依赖管理三要素
- 配置文件 描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod