【Go语言进阶】并发编程-依赖管理 | 青训营笔记

109 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天,今天学习的内容是Go的并发编程以及依赖管理,整理学习笔记如下。

3 Go语言上手 - 工程实践

3.1 Go语言进阶 - 并发编程

从并发编程的视角了解Go高性能的本质

代码:go-project-example/concurrence

并发&并行

image.png

Go可充分发挥多核优势,高效运行

3.1.1 Goroutine 协程

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

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

image.png

创建方法

使用普通函数创建: go 函数名(参数列表)

使用匿名函数创建:

 go func(参数列表){
     函数体
 }(调用参数列表)

3.1.2 CSP (Communicating Sequential Processes)

Go提倡通过通信共享内存而非通过共享内存实现通信

通过设置临界区来进行通信的话,很容易发生竞争等问题;而通过通道进行共享可以避免这个问题。

image.png

3.1.3 Chanel 缓冲通道

创建方法: make(chan 元素类型,[缓冲大小])

image.png

无缓冲通道(同步化),创建 make(chan int)

有缓冲通道,速度平衡,创建 make(chan int,2)

生产者消费者问题中使用有缓冲通道平衡结果输出与结果打印速度,避免因结果打印速度较慢导致数据丢失。

3.1.4 并发安全Lock

互斥锁简单声明调用

 lock sync.Mutex //声明
 lock.Lock()     //加锁
 lock.Unlock()   //解锁

协程Goroutine中对临界区进行操作时需要加锁进行处理避免数据并发安全问题。

3.1.5 WaitGroup

通过计数器可以在主线程中等待Goroutine执行完成退出

image.png

3.1.4&3.1.5参考文档 - Go的同步sync:pkg.go.dev/sync

3.2 Go语言进阶 - 依赖管理

了解Go语言依赖管理的演进路线

3.2.1 Go 依赖管理演进

image.png

3.2.2 GOPATH

  • 环境变量 $GOPATH

image.png

  • 项目代码直接依赖 src 下的代码

  • 通过 go get 下载最新版本的包到 src 目录下

弊端: 无法实现package的多版本控制(当某一package的某一被调用方法在不同版本可能未实现/实现不同)

3.2.3 Go Vendor

  • 在项目目录下增加 vendor 文件,所有依赖包的副本形式放在 $ProjectRoot/vendor

image.png

  • 依赖寻址方式: vendor -> GOPATH (先寻找项目根目录下的 vender 文件夹,若没有再到 GOPATH 中)
  • 每个项目可以保证自己的包版本满足自己的使用需求

弊端: 无法控制依赖版本,当项目更新时可能出现依赖冲突,导致编译错误。

image.png

3.2.4 Go Module

目标: 定义版本规则和管理项目依赖关系

  • 通过 go.mod 文件,管理依赖包版本
  • 通过 gp get / go mod 指令工具管理依赖包

go mod 常用命令:

  • go help module-getgo help gopath-get 分别去了解 Go modules 启用和未启用两种状态下的 go get 的行为

  • go get 拉取新的依赖

    • go get golang.org/x/text@latest 拉取最新的版本(优先择取 tag)
    • go get golang.org/x/text@master 拉取 master 分支的最新 commit
    • go get golang.org/x/text@v0.3.2 拉取 tag 为 v0.3.2 的 commit
    • go get golang.org/x/text@342b2e1 拉取 hash 为 342b231 的 commit,最终会被转换为 v0.3.2
  • go get -u 更新现有的依赖

  • go mod download 下载 go.mod 文件中指明的所有依赖

  • go mod tidy 整理现有的依赖

  • go mod graph 查看现有的依赖 结构

  • go mod init [模块名] 生成并初始化 go.mod 文件

  • go mod edit 编辑 go.mod 文件

    • -require gopkg.in/gin-gonic/gin.v1@v1.3.0go.mod 文件中加入该依赖
  • go mod vendor 导出现有的所有依赖(事实上 Go modules 正在淡化 Vendor 的概念)

  • go mod verify 校验一个模块是否被篡改过(使用 go.sum 校验哈希值)

3.2.5 依赖管理三要素

  1. 配置文件,描述依赖 - go.mod

    image.png

    版本规则:

    语义化版本 - ${MAJOR}.${MINOR}.${PATCH} 。major为大版本,不要求兼容;minor为小版本,一般用于增加函数/功能等;patch为补丁,一般用于bug修复等。(e.g. V1.3.0, V2.3.0)

    基于 commit 的伪版本 - vX.0.0-yyyymmddhhmmss-abcdefgh123 。前面版本号部分规则与语义化版本相同,后面为时间戳与hash校验码。

    indirect直接依赖:

    当前项目A依赖关系 A->B->C ,则对B为直接依赖,对C为间接依赖。

    image.png

    incompatible不兼容标示:

    • 主版本在v2以上的模块Go要求其在模块路径必须有一个匹配的主版本后缀 /vN ,这允许 go 命令将一个项目的多个主要版本视为不同的模块,即使它们是在同一个仓库开发的。

    • 但由于其要求较晚提出,而部分库已经发布。为了与这些存储库保持兼容性,go 命令将 +incompatible 后缀添加到具有主要版本 2 或更高版本的版本,而无需 go.mod 文件。+incompatible 表示版本是与具有较低主要版本号的版本相同的模块。因此,go 命令可以自动升级到更高的 +incompatible 版本,即使它可能会破坏构建。

    image.png

    参考文档:GoModules中文文档 - incompatible标示

    最低兼容版本:

    Go会选择当前项目依赖的某个库的最低兼容版本作为依赖版本。

    image.png

    1. (C项目 v1.4 兼容 v1.3 版本)
  2. 中心仓库管理依赖库 - Proxy

    作用: 缓存软件版本,保证依赖的稳定性

    image.png

    配置: 配置环境变量 GOPROXY

    image.png

  3. 本地工具 - go get/mod

    image.png image.png