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

33 阅读2分钟

Go语言进阶与依赖管理

一、并发与并行

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

1.Goroutine

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

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

2.CSP(Communicating Sequential Processes)

提倡通过通信共享内存(通道)而不是通过共享内存(临界区)实现通信

3.Channel

make(chan 元素类型,[缓冲大小])

  • 无缓冲通道 make(chan int) 同步
  • 有缓冲通道 make(chan int 2)
package main
//A子协程发送o-9数字,B子协程计算输入数字的平方,主协程输出最后的平方数
func main(){
    src := make(chan int)
    dest := make(chan int,3)
    go func(){
        //A
        defer close(src)
        for i := 0;i < 10; i++{
            src <- i
        }
    }()
    go func(){
        //B
        defer close(dest)
        for i := range src{
            dest <- i * i
        }
    }()
    //M
    for i := range dest{
        //复杂操作
        println(i)
    }
}

输出结果

0
1
4
9
16
25
36
49
64
81

4.并发安全Lock

image.png

不加锁的话共享内存会引发一些数据安全问题

5.WaitGroup

其实就是维护了一个计数器的实现

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

Add(delta int) 计数器+delta

Done()计数器-1

Wait()阻塞直到计数器为0

二、依赖管理

1.Go 依赖管理演进

GOPATH->Go Vendor -> Go Module

1.GOPATH

  • bin 项目编译的二进制文件
  • pkg 项目编译的中间产物,加速编译
  • src 项目源码

项目代码直接依赖src下的代码,go get 下载最新版本的包到src目录下

弊端:无法实现package的多版本控制

2.Go Vender

  • 项目目录下增加vender文件,所有依赖包副本形式放在项目根目录/vender
  • 依赖寻址方式:vender->GOPATH

无法控制依赖的版本,更新项目又可能出现依赖冲突,导致编译出错

3.Go Module

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

2.依赖管理三要素

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

1.依赖配置-version

语义化版本${MAJOR}.${MINOR}.${PATCH}

major:大版本,可以不兼容

minor:可以是新增了一些功能等,需要在major下做到兼容

patch:代码维护

基于commit伪版本 vx.0.0-yyyymmddhhmmss-abcdefgh1234

语义化版本号+提价的时间戳+提交的hash前缀

2.依赖配置-indirect

间接依赖,如:

A->B,B->C则A->C就是间接依赖,会有 //indirect标识

3.依赖配置-incompatible

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

4.依赖配置-依赖图

image.png

5.依赖分发-回源

  • 无法保证构建稳定性

    增加/修改/删除软件版本

  • 无法保证依赖可用性

    删除软件

  • 增加第三方压力

    代码托管平台负载问题

6.依赖分发-Proxy

稳定、可靠

7.依赖分发-变量GOPROXY

image.png

8.工具-go get

image.png

9.工具-go mod

image.png