Go 语言进阶与依赖管理 | 青训营笔记

76 阅读2分钟

语言进阶——Go并发编程

并发 VS 并行

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

1.png

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

2.png

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

协程 VS 线程

  • 协程:用户态,轻量级线程,栈KB级别
  • 线程:内核态,线程跑多个协程,栈MB级别

3.png

实例 Goroutine

快速打印 hello goroutine:0~hello goroutine:4 原理:通过并行输出

func hello(i int){
    Println("hello goroutine : "+fmt.Sprint(i))
}
func HelloGoRoutine(){
    for i:=0;i<5;i++ {//创建5个线程
        go func(j int){
            hello(j)
        }(i)
    }
    time.Sleep(time.Second)
}

运行结果:

4.png

CSP(Communicating Sequential Processes)

提倡通过通信共享内存而不是通过共享内存而实现通信

image.png

通道(Channel)的具体操作

make(chan 元素类型, [缓冲大小]) 典型的生产消费模型。

  • 无缓冲通道:make(chan int)
  • 有缓冲通道:make(chan int,2) (相当于货架)

5.png

func CalSquare(){
    src:=make(chan int)  //创建无缓冲通道
    dest:=make(chan int,3)  //创建有缓冲通道
    go func(){
        defer close(src)
        for i:=0 i<10;i++{
            src<-i
         }
      }()
      go func(){
          defer close(dest)
          for i:=range src{
              dest<-i*i
           }
       }()
       for i:=range dest{
           println(i)
        }

并发安全Lock

  • lock.lock()
  • lock.unlock()

WaitGroup

计数器:开启协程+1;执行结束-1;主协程阻塞直到计数器为0.

  • wq.Add()
  • defer wg.DOne()
  • wg.wait()

依赖管理

Go的依赖管理主要经历了三个阶段:GOPATH、Go Vendor、Go Module。

GOPATH

  • GOPATH是在系统设的环境变量,是Go项目的工作区,目录下的bin是项目编译的二进制文件,pkg是项目编译的中间产物,src是项目源码。项目代码直接依赖src下的代码,go get下载的包到src目录下。
  • 弊端:A和B依赖于某一package的不同版本,无法实现package的多版本控制。

Go Vendor

  • 依赖寻址方式:Vendor=>GOPATH
  • 通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题。
  • 弊端:无法控制依赖的版本。更新项目后又可能出现依赖冲突而导致编译出错。

Go Module

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

依赖管理三要素

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

依赖配置——version

语义化版本、基于commit伪版本。

依赖配置——indirect

  • A->B->C:A->B是直接依赖,A->是间接依赖。

依赖配置——incompatible

对于没有go.mod文件并且主版本2+的依赖,会+incompatible。 go在选择编译版本的时候会选择最低的兼容版本。(v1.3和v1.4选择v1.4)

依赖分发——变量GOPROXY

服务站点URL列表,“direct”表示源站

工具——go get

go get example.org / pkg +

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

工具——go mod

go mod+

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

测试

  • 回归测试
  • 集成测试
  • 单元测试
  • 从上到下,覆盖率逐层变大,成本却逐层降低

单元测试

6.png

  • 所有测试文件都以_test.go结尾
  • 方法命名是func Testxxx(*testing.T)
  • 初始化逻辑放到TestMain中

Mock测试

快速Mock函数:

  • 为一个函数打桩
  • 为一个方法打桩

基准测试

  • 优化代码
  • 内置测试框架已提供基准测试

项目实战

实现本地web服务。