这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天 主要有3个方面的内容:
- go进阶知识
- go 包管理
- go 测试
这三个方面一直是了解个大概,借此机会从课堂好好学学。
go进阶
go 使用goroutine并发执行程序,goroutine初始大小为 2-8kb,具体与go版本与操作系统版本有关。 go并发3大利器:channel、sync.Mutex、sync.WaitGroup
channel
如何优雅的从channel循环取值
- 接收值判断通道是否关闭
- 使用 for range
通道使用异常情况:
- Channel 满或者nil
写阻塞 - channel 为空或者nil
读阻塞 关闭已关闭的channel panic写已关闭的channel panic读已关闭channel 返回零值
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
// 向ch1发送数据
go func() {
for i := 0; i < 100; i++ {
ch1 <- i
}
close(ch1)
}()
// 从ch1读值,再写入ch2
go func() {
for {
i, ok := <-ch1 //通道关闭后ok为false
if !ok {
break
}
ch2 <- i
}
close(ch2)
}()
//从ch2接收值打印
for i := range ch2 { // 通道关闭后自动退出range循环
fmt.Println(i)
}
}
sync.Mutex的简单使用
var mu sync.Mutex
mu.Lock() // 加锁
do something // 临界资源
mu.Unlock() // 解锁
sync.WaitGroup的同步操作简单使用
var wg sync.WaitGroup
wg.Add(10) // 初始化并发任务数为10
go func() {
do something
wg.Done() // 每当1个协程完成操作任务数减1
}
wg.Wait() // 主程序阻塞至所有任务完成
go 包管理
go 依赖演进
1. GOPATH
使用环境变量 $GOPATH
--$GOPATH
--bin 编译后的二进制文件
--pkg 编译的中间产物
--src 源码
项目直接依赖src下源码、无法依赖某package不同版本
2. GO Vendor
使用一个副本文件夹Vvendor替换$GOPATH存储packages 但依旧无法控制依赖的版本,更新项目时容易产生依赖冲突
3. GO Module
通过 go.mod 文件管理依赖版本 go mod init、 go mod tidy、go get
go 单元测试
Go 语言推荐测试文件和源代码文件放在一块,测试文件以 _test.go 结尾。比如,当前 package 有 calc.go 一个文件,我们想测试 calc.go 中的 Add 和 Mul 函数,那么应该新建 calc_test.go 作为测试文件。
example/
|--calc.go
|--calc_test.go
源码
package main
func Add(a int, b int) int {
return a + b
}
func Mul(a int, b int) int {
return a * b
}
测试
package main
import "testing"
func TestAdd(t *testing.T) {
if ans := Add(1, 2); ans != 3 {
t.Errorf("1 + 2 expected be 3, but %d got", ans)
}
if ans := Add(-10, -20); ans != -30 {
t.Errorf("-10 + -20 expected be -30, but %d got", ans)
}
}
go test 自动执行当前目录下所有测试