go进阶与依赖管理 | 豆包MarsCode AI 刷题

76 阅读2分钟

多线程

协程

协程: 用户态, 轻量级线程, 栈KB级别 协程: 内核态, 线程跑多个协程, 栈MB级别 使用go关键字来开启一个协程

通道

提倡通过通信共享内存, 而不是通过共享内存实现通信 make(chan 元素类型,[缓冲大小]

  • 无缓冲通道(同步通道) make(chan int)
  • 有缓冲通道 make(chan int,2)
func CalSquare() {  
    src := make(chan int)  
    dest := make(chan int, 1)  
    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 {  
       time.Sleep(3000000000)  
       println(i)  
    }  
}

并发安全 Lock

lock sync.Mutex 对于共享内存来说, 有可能出现并发安全问题, 所以要对其加锁

WaitGroup

使用time.sleep时并不能确定应当让线程暂停的时间, 从而实现线程同步

Add(delta int)计数器+delta
Done()计数器-1
Wait()阻塞知道计数器=0
计数器: 开启协程+1, 执行结束-1; 主协程阻塞知道计数器为0
func CalSquare() {  
    var wg sync.WaitGroup  
    for i := 0; i < 5; i++ {  
       go func(j int) {  
          defer wg.Done()  
          println(j)  
       }(i)  
    }  
    wg.Wait()  
}

依赖管理

GOPATH->GO VENDOR -> GO Module

环境变量GOPATH

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

  • 项目源码直接依赖src下的代码
  • go get 下载最新版本的包到src目录下 弊端
  • 无法实现package的多版本控制

GO VENDOR

解决无法实现package的多版本控制的问题 | |-- Readme.md |-- dao |-- handler |-- mian.go |-- service |-- vendor

  • 项目目录下增加vendor文件, 所有依赖包副本形式放在$ProjectRoot/vendor
  • 依赖寻址方式: vendor -> GOPATH 通过每个项目引入一份依赖的副本, 解决了多个项目需要同一个package依赖冲突问题 弊端
  • 无法控制依赖的版本
  • 更新项目可能出现依赖冲突, 导致编译出错

GO Module

  • 通过go.mod文件管理依赖包版本
  • 通过go get/go mod 指令工具管理依赖包 类比maven
module github.com/wangkechun/go-by-example   依赖管理基本单元
  
go 1.18  原生库
  
require (  单元依赖  
	example/lib1 v1.0.2
    )

version

语义化版本 ${MAJOR(大版本)}${MINOR(新增函数/功能)}${PATCH(修改bug)} V1.3.0 V2.3.0 基于commit的伪版本 vx.0.0-yyyymmddhhmmss-${12位hash码前缀}

  • 主版本2+模块会在模块路径增加/vN 后缀
  • 对于没用go.mod文件并且主版本2+的依赖, 会+incompatible go在遇到依赖了同一个模块的不同版本时, 会选择依赖最低的兼容版本

go get

go get example.org/pkg +

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

go mod

go mod +

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

总结与思考

协程

用户态协程:轻量级线程,栈大小为KB级别。

内核态协程:运行在内核态的线程上,栈大小为MB级别。

Go中的协程:使用go关键字启动一个新的协程。

通道

通信方式:提倡通过通信共享内存,而不是通过共享内存实现通信。

通道创建:

无缓冲通道:make(chan int)

有缓冲通道:make(chan int, 2)