这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
Go语言进阶
goroutine
协程是轻量化的线程
特点
- 有独立的栈空间
- 共享程序堆空间
- 调度由用户控制
如果主线程退出了,则协程即使还没有执行完毕,也会退出 如果多个协程对资源进行写操作,会发生资源竞争 我们可以通过互斥锁解决
//定义一个全局变量互斥锁
//Mutex结构体有两个方法
//func (*Mutex)Lock 上锁
//func (*Mutex)Unlock 释放锁
var lock sync.Mutex
Channel
概念:
- channel本身是一个队列,先进先出
- 本身是有类型的,string,int等
- channel是引用类型,使用make创建,一旦make容量就确定。
- 线程安全,不需要加锁
- 当写满时,不可以写,发送将持续阻塞直到数据被接收。取空时,不可以取,接收将持续阻塞直到发送方发送数据。
- 每次接收一个元素
- 关闭之后,不能再写入,只能读。
//make(chan 元素类型,[缓冲大小])
//有缓冲通道
make(chan int, 10)
//无缓冲通道
make(chan int)
无缓冲通道读写必须同时操作,如果只进行读或者只进行写那么会被阻塞,被暂时停顿等待另外一方的操作
接收
1.阻塞接收数据
执行该语句时将会阻塞,直到接收到数据并赋值给 data 变量
data := <-ch
2.非阻塞接收数据
//data表示接收到的数据。**未接收到数据时,data 为通道类型的零值**
//ok表示是否接收到数据
data, ok := <-ch
3.接收数据但忽略
执行该语句时将会发生阻塞,直到接收到数据
<-ch
4.循环接收(重点)
在遍历管道之前要先关闭管道,因为在遍历时,如果channel没有关闭,当遍历完所有元素后,for循环还要读取下一个元素,就会阻塞出现deadlock的错误。而不是说channel没有关闭而无法进入循环,就算channel没有关闭依然能进入循环。在循环到最后一个元素前关闭channel,则退出循环
for data := range ch {
}
若channel的类型是interface{},则取出后需要解析类型断言
WaitGroup
依赖管理
GOPATH
项目代码直接依赖src下的代码
go get下载的包到src目录下
Go Module
1.配置文件,描述依赖 go.mod
2.中心仓库管理依赖 Proxy
3.本地工具 go get/mod
version
语义化版本
major大版本,minor新增功能,patch修复
${major}.${minor}.${patch}
v1.3.0
基于commit伪版本
//版本前缀 + 提交commit的时间戳
v1.2.0-20190725025543-5a6ddasdsad
go.mod
module gin_demo //依赖管理基本单元
go 1.19 //原生库
require ( //单元依赖
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.8.2 // indirect
github.com/go-playground/locales v0.14.1 // indirect
}
indirect关键字——间接依赖
测试
单元测试
规则
- 所有测试文件以_test.go结尾
- func Testxxx(*testing.T)
- 初始化逻辑放到TestMain中
例子
func TestSayHello(t *testing.T) {
var output = SayHello()
var except = "hello"
if output != except { //这里也可以调用一些assert包来判断
t.Errorf("no")
}
}
①直接运行该函数
②命令行
进入到该文件下执行go test
go test命令会遍历所有的*_test.go文件中符合命名规则的函数,然后生成一个临时的main包用于调用相应的测试函数,然后构建并运行、报告测试结果,最后清理测试中生成的临时文件。
代码覆盖率
--cover
mock
暂时没听懂
基准测试
func BenchmarkSelect(b *testing.B) {
InitServer()
b.ResetTimer()//重置时间
for i := 0; i < b.N; i++ {
Select()
}
}