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

64 阅读4分钟

Go语言进阶与依赖管理笔记

前言

这是我第一篇学习笔记,回顾了之前学过的内容,选择了《Go语言进阶与依赖管理》这节课作为这次笔记的来源,是因为我在这之前所编写的大部分代码中,几乎都是顺序执行,很少进行过多线程的程序设计。因此在上这次课时,Go语言中有关高并发的各种底层机制对我都是新奇的,这也是Go语言最重要的一个吸引我的特性。

1 并发编程

1.1 并发与并行

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

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

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

1.2 Goroutine

image.png

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

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

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

个人认为协程是比线程更加灵活的,首先创建线程的开销会更大,并且线程之间切换也会消耗大量的性能。但是对于协程来说,协程是轻量级的,这意味着协程的操作与线程相比,会降低大量开销,这也就带来了性能上的大幅提升。此外,由于线程处于更底层的位置,需要通过操作系统来进行管理。但是协程不一样,协程可以完全由程序控制,这也就是课程中所说的“用户态”,因此其没有内核切换的开销,从而使协程更具高性能。

这里再补充一点进程、线程与协程的关系:一个线程可以有多个协程,一个进程也可以单独拥有多个协程

1.3 CSP

CSP (Communicating Sequential Processes),即提倡通过通信共享内存而不是通过共享内存而实现通信。

为什么Go中是这样的呢?这里仅分享个人见解,如有误导,敬请指正:通过通信共享内存,最直观的影响就是防止不同的Goroutine之间因为一些误操作而造成对内存的错误更改。尤其是处于高并发的场景下,如果没有处理好安全问题,很容易引发各种严重错误。而通过通信共享内存,有利于筛除错误从而防止进一步的严重问题。

1.4 Channel

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

1.5-1.6 并发安全Lock WaitGroup

这两部分主要是代码的使用,不进行赘述。

2 依赖管理

“对于hello world以及类似的单体函数只需要依赖原生SDK,而实际工程会相对复杂,我们不可能基于标准库0~1编码搭建,而更多的关注业务逻辑的实现,而其他的涉及框架、日志、driver、以及collection等一系列依赖都会通过sdk的方式引入,这样对依赖包的管理就显得尤为重要”

当我们在进行团队协作时,项目依赖管理不仅便于自己写代码,同时也能让协作者更清晰地了解项目是通过什么部分构成的,这在工程化项目中是尤为重要的。

2.1 GOPATH

特点

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

弊端

  • 若A和B依赖于某一package的不同版本,则无法实现package的多版本控制

2.2 GOPATH

特点

  • 项目目录下增加vendor文件,所有依赖包副本形式放在$ProjectRoot/vendor
  • 依赖寻址方式: vendor => GOPATH
  • 通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题。

弊端

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

2.2 GOPATH

特点

  • 项目目录下增加vendor文件,所有依赖包副本形式放在$ProjectRoot/vendor
  • 依赖寻址方式: vendor => GOPATH
  • 通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题。

弊端

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

2.3 Go Module

特点

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

弊端

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

Go Modules 是Go语言官方推出的依赖管理系统,解决了之前依赖管理系统存在的诸如无法依赖同一个库的多个版本等问题。Go Modules 是Go语言官方推出的依赖管理系统,解决了之前依赖管理系统存在的诸如无法依赖同一个库的多个版本等问题, Go Modules从Go 1.11开始实验性引入,Go 1.16默认开启;一般都读为go mod。