Go Module
简介
- 通过
go.mod文件管理依赖包版本 - 通过
go get/go mod指令工具管理依赖包 - 终极目标
- 定义版本规则和管理项目依赖关系
依赖管理三要素
- 配置文件,描述依赖
go.mod(类比cargo) - 中心仓库管理依赖库
Proxy(类比crates.io) - 本地工具
go get/mod
配置go.mod
module example/project/app 依赖管理的基本单元
(有的时候大项目里面的小项目就得则么写,类比c++中src下面的CMakeList.txt)
(或者一个大包,但是别人只想用里面的小包)
go 1.16 原生库
require( 单元依赖
example/lib1 v1.0.2
example/lib2 v1.0.0 //indirect
example/lib6 v3.2.0+incompatible
//...
)
依赖配置-version
-
语义化版本
- ${MAJOR}.${MINOR}.${PATCH}
- MAJOR:大版本,不同的MAJOR间认为是代码不兼容的
- MINOR:新增函数或功能,需要保持MAJOR下的兼容性
- PATCH:部分
bug的修复
- V1.3.0
- V2.3.0
- ${MAJOR}.${MINOR}.${PATCH}
-
基于
commit伪版本- vX.0.0-yyyymmddhhmmss-abcdefg1234
- 版本前缀-时间戳-哈希码前缀
- v0.0.0-20220401081311-c38fb921298
- v1.0.0-20201130134442-10cb123792679c6c
- vX.0.0-yyyymmddhhmmss-abcdefg1234
-
indirtect
graph LR
A(A)
B(B)
C(C)
A-->B-->C
-
A -> B:直接依赖
-
A -> C:间接依赖,使用indirtect进行标识
-
incompatible
- 对于没有
go.mod文件而且主版本2+的依赖,会+incompatible
- 对于没有
-
最低兼容算法
依赖分发-回源
graph TB
A(Github)
B(SVN)
C("...")
D(Developer)
A-->D
B-->D
C-->D
-
问题
- 无法保证构建的稳定性和依赖的可用性
- 增加第三方压力
-
解决方法Proxy
graph TB
A(Github)
B(SVN)
C("...")
D(Proxy)
E(Developer)
A-->D
B-->D
C-->D
D-->E
- (类比crates.io),自己构建大仓库保证稳定性
GOPROXY="https://proxy1.cn, https://proxy2.cn, direct"(direct表示源站)
graph LR
A(Proxy1)
B(Proxy2)
C(Direct)
A-->B-->C
- 我的配置:
GOPROXY=https://proxy.golang.com.cn,direct
工具-go get
- go get example.org/pkg
- @update 默认
- @none 删除依赖
- @v1.1.2
tag版本,语义版本 - @23dfdd5 特定的
commit - @master 分支最新的
commit
工具-go mod
- go mod
- init 初始化,创建go.mod文件
- download 下载模块到本地缓存
- tidy 增加需要的依赖,删除不需要的依赖
总结
- go.mod
- Proxy
- go get/mod
测试
单元测试流程
graph LR
A(输入)
C(输出)
D(期望)
E(校对)
A--"测试单元"-->C-->E
D-->E
- 测试单元
- 函数
- 模块
- ...
规则
-
所有测试文件以
_test.go结尾(如publish_post_test.go) -
func TestXxx(*testing.T)(如func TestPublishPost(t *testing.T)) -
初始化逻辑放到TestMain中
-
例子
publish_post.go
package main
func HelloTom() string {
return "Jerry"
}
publish_post_test.go
package main
import "testing"
func TestMain(t *testing.T) {
output := HelloTom()
exceptOutput := "Tom"
if output != exceptOutput {
t.Errorf("Expect %v, but output %v", exceptOutput, output)
}
}
(校对部分建议使用开源的assert包)
- 执行效果
$ go test
--- FAIL: TestMain (0.00s)
publish_post_test.go:9: Expect Tom, but output Jerry
FAIL
exit status 1
FAIL learing_go 0.261s
覆盖率
-
覆盖度,越高代码的正确性越好
-
示例
package main
func HelloTom() string {
return "Jerry"
}
func JudgePassLine(score int16) bool {
if score >= 60 {
return true
}
return false
}
package main
import (
"testing"
)
func TestMain(t *testing.T) {
output := HelloTom()
exceptOutput := "Jerry"
if output != exceptOutput {
t.Errorf("Expect %v, but output %v", exceptOutput, output)
}
isPass := JudgePassLine(70)
if isPass != true {
t.Errorf("Expect %v, but output %v", true, isPass)
}
}
$ go test --cover
PASS
coverage: 27.3% of statements
ok learing_go 0.260s
- 如果加上修改
func JudgePassLine(score int16) bool {
return score >= 60
}
$ go test .\publish_post_test.go .\publish_post.go --cover
ok command-line-arguments 0.254s coverage: 100.0% of statements
单元测试-依赖
graph LR
A(单元)
B(File)
C(DBS)
D(Cache)
A-->B
A-->C
A-->D
graph LR
A(幂等)
B(稳定)
C(Mock)
A-->C
B-->C
-
幂等:每次运行结果一样(应该涉及了并发的问题,暴力测试)
-
稳定:任何时间,任何函数进行独立运行
-
Mock
基准测试
-
优化分析代码
-
内置
-
示例
package main
import (
"math/rand"
)
var ServerIndex [10]int
func InitServerIndex() {
for i := 0; i < 10; i++ {
ServerIndex[i] = i + 100
}
}
func Select() int {
return ServerIndex[rand.Intn(10)]
}
package main
import (
"testing"
)
func BenchmarkSelect(b *testing.B) {
InitServerIndex()
b.ResetTimer()
for i := 0; i < b.N; i++ {
Select()
}
}
func BenchmarkSelectParallel(b *testing.B) {
InitServerIndex()
b.ResetTimer()
b.RunParallel(func(p *testing.PB) {
for p.Next() {
Select()
}
})
}
Running tool: D:\Go\bin\go.exe test -benchmem -run=^$ -bench ^BenchmarkSelect$ learing_go
goos: windows
goarch: amd64
pkg: learing_go
cpu: AMD Ryzen 9 5900HX with Radeon Graphics
BenchmarkSelect-16 175706265 6.498 ns/op 0 B/op 0 allocs/op
PASS
ok learing_go 2.053s
Running tool: D:\Go\bin\go.exe test -benchmem -run=^$ -bench ^BenchmarkSelectParallel$ learing_go
goos: windows
goarch: amd64
pkg: learing_go
cpu: AMD Ryzen 9 5900HX with Radeon Graphics
BenchmarkSelectParallel-16 30002550 38.89 ns/op 0 B/op 0 allocs/op
PASS
ok learing_go 1.409s