Go语言进阶与测试 | 青训营笔记

45 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 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
image.png

依赖管理

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) image.png
  • 初始化逻辑放到TestMain中 image.png

例子

func TestSayHello(t *testing.T) {
   var output = SayHello()
   var except = "hello"
   if output != except { //这里也可以调用一些assert包来判断
      t.Errorf("no")
   }
}

①直接运行该函数
②命令行 进入到该文件下执行go test image.png
go test命令会遍历所有的*_test.go文件中符合命名规则的函数,然后生成一个临时的main包用于调用相应的测试函数,然后构建并运行、报告测试结果,最后清理测试中生成的临时文件。

代码覆盖率
--cover
image.png
mock
暂时没听懂

基准测试

func BenchmarkSelect(b *testing.B) {
   InitServer()
   b.ResetTimer()//重置时间
   for i := 0; i < b.N; i++ {
      Select()
   }
}

image.png