Go工程学习笔记 | 青训营

74 阅读3分钟

并发

协程

多线程在一个核上运行称为并发,在多核上运行称为并行,Go语言有Goroutine,为协程,用户态,有Go语言控制,是轻量级线程,KB级别.而线程是内核态,一个线程可以运行多个协程,线程是MB级别.

  • 启动协程

    使用关键字go+函数名,即可创建该函数的协程

通信(CSP)

Go提倡通过通信共享内存而不是通过共享内存来实现通信,因此要通过通道来实现不同协程间的通信,通道类似队列,先入先出.但Go也保留使用共享内存实现通信的功能,该功能需要加锁获取临界区权限,这样会发生竞争,影响并发效率

Channel

通过make(chan 元素类型,[缓冲大小])来创建一个通道,若不添加第二个参数则创建无缓冲通道,否则创建一个有缓冲通道,带有指定大小的缓冲区

生产消费模型示例

func main() {
    src := make(chan int)
    dest := make(chan int, 2)
    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()即可为该变量加锁

var(
    x int64
    lock sync.Mutex
)

WaitGroup并发同步

为了实现线程同步,可以使用time.sleep()方法,但更好的方法是通过WatiGroup进行优化

WaitGroup用于在执行多个 goroutine 时等待它们全部完成后再继续执行主程序。协调多个 goroutine 之间的同步,以确保所有 goroutine 都已完成其任务。

WaitGroup 包含以下几个主要方法:

  1. Add(delta int): 用于增加等待的 goroutine 的数量。通常在启动一个新的 goroutine 之前调用 Add 方法,将等待计数器加一。
  2. Done(): 表示一个等待的 goroutine 已完成其任务。在 goroutine 完成其工作后调用 Done 方法,将等待计数器减一。
  3. Wait(): 阻塞主程序的执行,直到所有的 goroutine 都调用了 Done 方法,并且等待计数器归零。

依赖管理

开发项目中要学会站在巨人的肩膀上,使用已经开发完成的组件来帮助开发,避免重复发明轮子需要导入依赖,框架等,因此需要合理地管理依赖库,目前广泛应用Go Module

依赖管理的目标是解决不同环境(项目)的依赖版本不同以及控制依赖库的版本

GOPATH

Go语言的环境变量,该目录下

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

弊端是:若项目A和B依赖于同一package的不同版本,在升级过程中package函数可能发生改变,导致两个项目无法同时构建成功

Go Vendor

添加vendor,为每一个项目引入一份依赖副本,解决版本不同的问题

存在的问题是,package A和package B又依赖了不同的下一层package,而他们又不兼容,就会再次导致冲突

Go Module

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

依赖管理三要素:

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