day02go语言进阶| 青训营笔记

48 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

Go笔记

Day_02进阶语法

语言进阶

并发VS并行

并发:多线程程序在一个核的cpu上运行

image-20230116101110301

并行:多线程程序在多个核的cpu上运行

image-20230116101130945

Go可以充分发挥多核优势,高效运行,为并发而生

Goroutine线程/协程

image-20230116101533607

协程:用户态,轻量级线程,栈KB级别

线程:内核态,线程跑多个协程,栈MB级别

//为函数创建一个协程
go functionName(){
​
}
//函数名前面加一个go关键字

协程之间的通信提倡采用通信实现共享内存,使用通道进行

image-20230116102323524

Channel通道

是一个引用数据类型

//定义方法
make(chan type,[缓冲大小])
//无缓冲
make(chan,int)
//有缓冲
make(chan,int,2)

image-20230116102738868

并发安全Lock

示例:对变量执行2000次+1的操作,5个协程并发执行

var (
    number int64
    lock   sync.Mutex
)
//不加锁的情况下,边界值处会有所影响,导致计算结果有误差
func numberAddOutLock() {
    for i := 0; i < 2000; i++ {
        number += 1
    }
}
//加锁的情况下,边界值处不会有影响,计算结果精确
func numberAddLock() {
    for i := 0; i < 2000; i++ {
        lock.Lock()
        number += 1
        lock.Unlock()
    }
}
//测试类
func TestNumberAdd(t *testing.T) {
    number = 0
    for i := 0; i < 5; i++ {
        go numberAddOutLock()
    }
    time.Sleep(time.Second)
    //没有加锁,结果不精确输出
    fmt.Println("outLock:", number)
    
    number = 0
    for i := 0; i < 5; i++ {
        go numberAddLock()
    }
    time.Sleep(time.Second)
    //加了锁,结果精确输出
    fmt.Println("lock:", number)
​
}
WaitGroup

Add:计数器+delta

Done:计数器-1

Wait:阻塞直到计数器为0

处理并发

依赖管理

GoPath

bin 编译的二进制文件

pkg 编译的中间产物

src 项目源码

无法实现多版本的pkg控制

GoVendor

无法控制依赖的版本,可能造成依赖冲突

GoModel
  • 通过go.mod文件管理依赖包版本
  • 通过go get/go mod指令工具管理依赖
  • 定义版本规则、管理项目依赖
依赖管理三要素
  1. 配置文件,描述依赖 go.mod
  2. 中心仓库管理依赖库 Proxy
  3. 本地工具 go get/mod

image-20230116133221354

依赖配置-version
语义化版本

MAJOR.{MAJOR}.{MINOR}.${PATCH}

V1.3.0

V2.3.1

基于commit伪版本

vx.0.0-yyyymmddhhmmss-abcdefgh1234

v0,0,0-202201012108-c38fb5932b7

依赖配置-indirect

非指定依赖

依赖配置-incompatible

主版本2+模块会在模块路径增加/vN后缀。 对于没有go.mod文件并且主版本2+的依赖,会+incompatibe

image-20230116134124434

Go会选择最低兼容版本

依赖分发-回源

image-20230116134247271

使用git去代码仓库拉去依赖

依赖分发-Proxy

image-20230116134758985

如果采用默认的GOPROXY,会容易出现错误,因为默认的是国外网站,所以一般需将GOPROXY值改成国内URL

//查看go环境
go env
​
//修改GOPROXY的地址
go env -w GOPROXY="https://goproxy.cn"

image-20230116135526614

image-20230116135547051

单元测试

保证质量提高效率

  • 所有测试文件以_test.go结尾
  • image-20230116140841164
  • func TestXxxx(*testing.T)
  • image-20230116140854821
  • 初始化逻辑放到TestMain中
Tips
  • 一般覆盖率:50%~60%,较高覆盖率80%+
  • 测试分支相互独立、全面覆盖
  • 测试单元粒度足够小,函数单一职责