Go语言进阶(工程进阶01)| 青训营笔记

106 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天。今天依旧是通过过往的编程经验,来对比go,从而更快掌握。过程中提出问题,便于更深入了解。

概要

  1. 并发编程(语言方面)
  2. 依赖管理(项目方面管理第三方包)

语言进阶(高并发)

并发or并行

狭义的并发指分频,并行指多核并行。广义上并行是并发的一种。

go语言通过高效的调度模型,发挥多核优势。(并发or并行?)

协程and线程

协程是用户态,线程是内核态;线程跑多个协程;线程栈MB,协程KB(这是老师讲的,究竟哪个是轻量级,和进程是哪种层级区分,PPT标注错误,MB和KB反过来);go可跑上万个协程

协程

快速:多协程,在调用函数时,加一个协程关键字go,创建一个协程运行该函数(并行)

子协程运行完前,主协程不退出。可先用time.Sleep(time.Second)

协程通信(通信与内存)

通过通信,共享内存 而不是通过共享内存实现通信。

通道(消息传递)和临界区(内存加锁)的区别。通道Channel,先进先出。

通道

make(chan int) make(chan int,2)

无缓冲通道(同步通道)和有缓冲通道(容量,存在通道阻塞)

问题:为什么13:32,能保证顺序性,就指协程安全,这里只能说明先进先出,并不能说明不同协程中,谁先进通道。从理论上来说,channel的先进先出。

  • 该时刻的例子真正有意思的在于,for range 在多协程的情况下,保证了channel全部输出,不重复。

带缓冲的队列,好处是,进出不均衡时,不影响效率。进:生产,出:消费。

问题:那无缓冲的通道,进大于出,会出现什么情况,阻塞吗,还是丢失?

临界区(保留的传统方式)

是否使用 锁 会影响结果。并发安全LOCK。

问题:对一个数加2000次这种,使用通道,是否会并发安全,这种情况下,并发的本质,是不是还是排序。

  • 这个角度上,是安全的,毕竟非读,只入,非顺序,不用在意中间态。本质上,其实类似锁。

协程阻塞

使用固定时间的time.Sleep(time.Second) 是一种浪费,不如用waitGroup。类似其他语言(如shell)里面的wait与sleep的区别。go的waitGroup,提供Add +delta(在总数上加),Done -1, Wait 阻塞至0,计数器的方式,进行阻塞,类似于Linux多线程编程时,封装的线程锁。

依赖管理

除标准库,第三方包和库的管理,避免造轮子。

框架、日志、集合等,通过SDK

  • Gopath
  • Go Vendor
  • Go Module

不同项目依赖的版本不同,控制依赖库的版本。(是否类似于maven 、 pom)(和python版本管理的区别在哪,会不会也出现不同版本相互之间版本兼容问题)

GOPATH

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

项目代码直接依赖src下的代码,把包用 go get 直接下到src里面。

弊端:A和B项目同时依赖某一package的不同版本,版本不兼容时,无法多版本控制,只能实现一个。(是类似java中maven的统一仓库一样,但没法管理,多版本共存吗)

Go Vendor

每个项目单独存放包的副本,解决多个项目版本冲突问题。但依赖的依赖,无法控制。(类似于前端的nodemodules,但不全放)

Go Module

通过go.mod文件管理依赖包,通过 go get / go mod 指令工具管理项目依赖**(与maven和pom文件十分类似)**

go.mod描述依赖,Proxy中心仓库管理依赖库,go get/mod 作为本地工具

go.mod 类似 pom

依赖配置-version

语义化版本 VMAJOR.{MAJOR}.{MINOR}.${PATCH} major间代码不兼容,隔离。MINOR保证同一major兼容的情况下,加了函数或特性。PATCH做代码BUG修复。

基于commit的伪版本

indirect 间接依赖 , incompatible 标识可能存在的不兼容

依赖配置-依赖图

A和B依赖了不同的C版本,在存在兼容的情况下,会选择一个满足兼容的最低版本

依赖分发-回源

Github、SVN ——> Proxy ——> Developer

Proxy保证依赖稳定性。

依赖分发-变量GOPROXY

工具-go get

依赖管理 下载拉取指定条件的包 (针对包)

工具-go mod

init download tidy (针对项目)