这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记
语言进阶
Golang的并发编程的讲解。
-
并发:多线程程序在一个核的cpu上运行
-
并行:多线程程序在多个核的cpu上运行
-
线程:内核态,线程跑多个协程,栈MB级别
-
协程:用户态,轻量级线程,栈KB级别
协程之间通过通信共享内存 -- 使用channel(通道)
channel
make(chan 元素类型 [缓冲大小])
//有缓冲通道
make(chan int, 2)
//无缓冲通道 同步通道
make(chan int)
简单的channel通信样例
func CalSquare(){
src := make(chan int)
dest := make(chan int, 2)
go func() {
defer close(src) //函数最后结束时关闭channel
for i := 0; i < 10; i ++ {
src <- i //将i放入管道,由于src无缓冲放入后在被接收前,协程将被堵塞
}
}()
go func() {
defer close(dest)
for i := range src {
dest <- i * i //由于dest存在缓冲,当dest中缓冲未满的状态时,可以连续接收src传递的数据
}
}()
for i := range dest{
//可能消费速度比生产速度慢,所以使用了有缓冲的chan
println(i)
}
}
并发安全Lock
var (
x int64
lock sync.Mutex
)
func addWithLock() {
for i := 0; i < 2000; i ++ {
lock.Lock()
x += i
lock.UnLock()
}
}
func addWithoutLock() {
for i:= 0; i < 2000; i ++ {
x += 1
}
}
WaitGrouo
Add(delta int) 计算器+delta Done() 计算器-1 Wait() 阻塞直到计数器为0
计数器
开启协程+1 执行结束-1 主协程阻塞到计数器为0
func ManyGoWait() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i ++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
依赖管理
- 工程项目不可能基于标准课0~1编码搭建
- 管理依赖库
GOPATH -> Go Vender -> GoModule
GOPATH工作模式的弊端
- 没有版本控制概念
- 无法同步一次第三方版本号
- 无法指定当前项目引用的第三方版本号 我们一般使用GoModule
(1) go mod命令
| 命令 | 作用 |
|---|---|
| go mod init | 生成 go.mod 文件 |
| go mod download | 下载 go.mod 文件中指明的所有依赖 |
| go mod tidy | 整理现有的依赖 |
| go mod graph | 查看现有的依赖结构 |
| go mod edit | 编辑 go.mod 文件 |
| go mod vendor | 导出项目所有的依赖到vendor目录 |
| go mod verify | 校验一个模块是否被篡改过 |
| go mod why | 查看为什么需要依赖某模块 |
GOPROXY
这个环境变量主要是用于设置 Go 模块代理(Go module proxy),其作用是用于使 Go 在后续拉取模块版本时直接通过镜像站点来快速拉取。
GOPROXY 的默认值是:https://proxy.golang.org,direct
proxy.golang.org国内访问不了,需要设置国内的代理.
如:
$ go env -w GOPROXY=https://proxy.golang.com.cn,direct
GOPROXY 的值是一个以英文逗号 “,” 分割的 Go 模块代理列表,允许设置多个模块代理,假设你不想使用,也可以将其设置为 “off” ,这将会禁止 Go 在后续操作中使用任何 Go 模块代理。
如:
$ go env -w GOPROXY=https://goproxy.cn,https://mirrors.aliyun.com/goproxy/,direct
direct
而在刚刚设置的值中,我们可以发现值列表中有 “direct” 标识,它又有什么作用呢?
实际上 “direct” 是一个特殊指示符,用于指示 Go 回源到模块版本的源地址去抓取(比如 GitHub 等),场景如下:当值列表中上一个 Go 模块代理返回 404 或 410 错误时,Go 自动尝试列表中的下一个,遇见 “direct” 时回源,也就是回到源地址去抓取,而遇见 EOF 时终止并抛出类似 “invalid version: unknown revision...” 的错误。
使用go get下载包
测试
单元测试
- 所有测试文件以_test.go结尾
- func TestXxx(*testing.T)
- 初始化逻辑放在TestMain中
覆盖率
如何衡量代码是否经过了足够的测试 如何评价项目的测试水准 如何评估项目是否达到了高水准测等级
- 一般覆盖率:50%~60% 较高覆盖率80%
- 测试分支相互独立
- 测试单元粒度足够小,函数单一职责
依赖
外部依赖 => 稳定&幂等
Mock测试
monkey: github.com/bouk/monkey
快速Mock函数
- 为一个函数打桩
- 为一个方法打桩
基准测试
- 优化代码
- 内置的测试框架提供了基准测试的能力