并发基础与依赖管理 | 青训营

141 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第 3 篇笔记

并发编程-基础

Goroutine

协程,又叫轻量级线程。与传统的系统级线程和进程相比,协程最大的优势在于“轻量级”。可以轻松创建上万个而不会导致系统资源衰竭。而线程和进程通常很难超过1万个。这也是协程别称“轻量级线程”的原因。

一个 线程 中可以有任意多个 协程,但某一时刻只能有一个协程在运行,多个协程分享该线程分配到的计算机资源

Go 在语言级别支持协程,叫 goroutine。Go 语言标准库提供的所有系统调用操作(包括所有同步IO操作),都会出让CPU给其他 goroutine。这让轻量级线程的切换管理不依赖于系统的线程和进程,也不需要依赖于CPU的核心数量。

Go 语言为并发编程而内置的上层API基于顺序通信进程模型 CSP(communicating sequential processes)。这就意味着显式锁都是可以避免的,因为Go通过相对安全的通道发送和接受数据以实现同步,这大大地简化了并发程序的编写。

CSP 模型是上个世纪七十年代提出的,用于描述两个独立的并发实体通过共享的通讯 channel(管道) 进行通信的并发模型。 CSP 中 channel 是第一类对象,它不关注发送消息的实体,而关注与发送消息时使用的 channel。

Channel

channel 是被单独创建并且可以在进程之间传递,类似于管道,它的通信模式类似于 boss-worker 模式的,一个实体通过将消息发送到channel 中,然后又监听这个 channel 的实体处理,两个实体之间是匿名的,这个就实现实体中间的解耦,其中 channel 是同步的一个消息被发送到 channel 中,最终是一定要被另外的实体消费掉的,在实现原理上其实是一个阻塞的消息队列。

/* 
定义一个channel时,也需要定义发送到channel的值的类型。channel可以使用内置的make()函数来创建:
chan是创建channel所需使用的关键字。Type 代表指定channel收发数据的类型。
​
*/
make(chan Type)  //等价于make(chan Type, 0)
make(chan Type, capacity)
/*
channel非常像生活中的管道,一边可以存放东西,另一边可以取出东西。
channel通过操作符 <- 来接收和发送数据,发送和接收数据语法:
*/
 channel <- value      //发送value到channel
<-channel             //接收并将其丢弃
x := <-channel        //从channel中接收数据,并赋值给x
x, ok := <-channel    //功能同上,同时检查通道是否已关闭或者是否为空

Sync

依赖管理

Go 依赖管理演进: GOPATH -> Go Vender -> Go Module

GOPATH

  • 环境变量 $GOPATH。
  • 项目代码直接依赖 src 下的代码。
  • 通过 go get 下载最新版本的包到 src 目录下。

弊端

  • 项目必须写在 GOPATH 下。
  • 没有内置的对扩展包的版本追踪。当项目 A 和项目 B 依赖于某一 package 的不同版本时,无法实现 package 的多版本控制。
  • 执行 go get 时,无法通过指定来拉取指定的版本

Go Vendor

  • 依赖于 GOPATH
  • 项目目录下增加 vendor 文件,将所有依赖包副班形式放在 $ProjectRoot/vendor 下。编译的时候将从 vendor 目录中查找依赖而不从 GOPATH/src 中对应目录中查找。
  • 解决了多个项目需要同一个 package 依赖的冲突问题。

弊端

  • 无法控制依赖的版本。
  • 更新项目容易出现依赖冲突,导致编译出错。

Go Module

  • 通过 go.mod 文件管理依赖包版本
  • 通过 go get/go mod 指令工具管理依赖包
  • 可以定义版本规则和管理项目依赖关系

依赖管理三要素

  1. 配置文件, 描述依赖 (go.mod)
  2. 中心仓库管理依赖库 (Proxy)
  3. 本地工具 (go get/mod)

工具

go get example.org/pkg

  • @update 默认
  • @none 删除依赖
  • @v1.1.2 tag 版本, 语义版本
  • @23dfdd5 特定的 commit

go mod

  • init 初始化 go.mod 文件
  • download 下载模块到本地缓存
  • tidy 增加需要的依赖, 删除不需要的依赖