这是我参与「第五届青训营 」伴学笔记创作活动的第2天。
今天的课程内容为:
- Go 语言进阶
- Goroutine
- Channel
- 并发安全Lock
- Go 依赖管理
- Gopath
- Go Vendor
- Go Module
- Go 测试
- 单元测试
- Mock测试
- 基准测试
- Go项目实战
- 社区话题页面
Go语言进阶
Goroutine
Golang中的Goroutine(协程)赋予了Golang强大的并发能力,Goroutine是一种轻量级的线程,由Golang来进行管理调度,同一时间内,Golang可以创建成千上万个Goroutine。
func HelloGoRoutine() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
fmt.Println("hello goroutine: " + fmt.Sprint(i))
}(i)
}
wg.Wait()
}
Channel
make(chan 元素类型, [缓冲大小])
- 无缓冲通道 make(chan int)
- 有缓冲通道 make(chan int, 2)
func CalSquare() {
src := make(chan int)
dest := make(chan int, 2)
go func() {
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
}()
go func() {
for i := range src {
dest <- i * i
}
}()
for i := range dest {
fmt.Println("%s", i)
}
}
并发安全Lock
Golang推荐使用通道进行通信而非共享内存进行通信。
通过sync.Mutex生成锁,进行共享内存进行通信。
var (
x int64
lock sync.Mutex
)
Go依赖管理
Gopath
最早期的依赖管理方案,直接将依赖安装在统一的src目录下,通过go get将最新版本的依赖包下载至src目录下。
这么做的弊端在于无法实现package的多版本控制,当本地两个项目依赖于同一个包的不同版本时,项目将会发生冲突。
Go Vendor
在项目目录下增加vendor文件夹,所有的依赖包副本都放在vendor文件夹中,通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题。依赖的寻址方式为vendor文件夹=>GOPATH。
这么做的弊端在于无法控制依赖的版本。
Go Module
- 通过go.mod文件管理依赖包版本
- 通过go get/go mod指令工具管理依赖包
对于非直接依赖的库(A -> B -> C,即C为A的非直接依赖库),go.mod文件中会以indirect标明
Go在进行依赖版本选择时,会主动选择最低的兼容版本。
Go测试
单元测试
- 所有测试文件以_test.go结尾
- 测试函数名以Test开头,形如func TestXxx(t *testing.T)
- 初始化逻辑放到TestMain中,func TestMain(m *testing.M)
func TestMain(m *testing.M) {
//测试前:数据装载,配置初始化等前置工作
code := m.Run()
//测试后:释放资源等收尾工作
os.Exit(code)
}
覆盖率通过计算测试代码的行数/总行数来得到。
Mock测试
通过Mock打桩函数去替换和File,DB,cache相关的一些外部依赖函数,来测试其他的逻辑部分。这样我们就可以消除网络或者其他不稳定因素的影响来进行代码的测试。可以在第三方库中找到大量的Mock测试的包,例如:github.com/bouk/monkey
基准测试
- 测试函数以Benchmark开头,形如func BenchmarkXxx(b *testing.B)
- 通过b.ResetTimer()重制计时器
- 通过b.RunParallel()来进行并行测试
Golang的math/rand中存在全局锁,因此,在高并发的场景下,推荐使用fastrand。
Go项目实战
社区话题页面
-
Go Mod
- go mod init
- go get gopkg.in/gin-gonic/gin.v1@v1.3.0