Go工程实践 | 青训营笔记
这是我参与「第五届青训营」伴学笔记创作活动的第2天
从一个Javaer的角度来学习Go
并发
相比于Java,Go的并发表现就优秀多了,根本原因还是在于协程以及语言层面的调度
协程
我们都知道相比于进程,线程是更轻量化的表现形式,在系统层级,CPU调度的基本单位也是线程;但线程能不能更加轻量化呢?这就引出了协程的概念
在Go中开启一个协程也很简单,只需要在方法调用之前添加关键字go即可
CSP
Go不同于其他语言,不使用共享内存来进行通信,而是通过通信来共享内存,这就需要channel
channel用于多个协程之间数据的传递和同步
make(chan int) //无缓冲通道
make(chan int, cap) //有缓冲通道
并发安全
由于也会出现同时读/写变量的情况,因此临界资源也是需要保护的,Go中的Mutex同互斥锁,WaitGroup同Java中的CountDownLatch
依赖管理
Go的依赖管理主要经历了三个阶段:GOPATH->Go Vendor->Go Module
GOPATH
在GOPATH下,主要有三个目录bin(存放编译产生的二进制文件)、pkg(存放编译的中间产物,加速编译)和src(源码)。当我们下载依赖库时,直接存放到src目录下,这样就会出现一个问题——我们不能依赖同一个package的不同版本,因为src目录下只能有一个版本
Go Vendor
为了解决上述问题,我们给每个项目的目录下增添一个vendor目录,当我们寻找依赖时,会先去vendor目录下寻找,在这种情况下,我们只需要将重复但不同版本的package分别放到不同项目的vendor目录下即可。
但Go Vendor仍然无法解决间接依赖同一个package不同版本的问题。
Go Module
类似于Maven,Go Module通过指定版本来唯一标识依赖,配置文件即go.mod
版本可分为语义化版本和commit版本。语义化版本格式为v{MINOR}.${PATCH},其中MAJOR为大版本号,大版本可以不兼容,MINOR一般认为是新增方法,需要兼容,PATCH则为修复bug。commit版本格式为vx.0.0-yyyymmddhhmmss-abcdefgh1234(12位hash前缀)
测试
单元测试
单元测试文件必须以_test.go结尾,测试函数命名必须以Test开始
func HelloTom() string {
return "Tommy"
}
func TestHelloTom(t *testing.T) {
output := HelloTom()
expect := "Tom"
if output != expect {
t.Errorf("Expected %s don't match actual %s", expect, output)
}
}
func TestMain(m *testing.M) {
code := m.Run()
os.Exit(code)
}
通过go test -cover可以查看覆盖率,一般来说覆盖率需要达到50%~60%
基准测试
func BenchmarkName(b *testing.B) {
for i := 0; i < b.N; i++ {
//function
}
}
使用go test -bench=.进行基准测试