Go语言工程实践,课程笔记 | 青训营笔记

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记

1: Go的高性能本质

Go语言通过并发性能极高的调动模型实现最大限度的资源利用,充分发挥多核计算机的性能优势。

协程:用户态,轻量级线程,栈KB级。轻量级,用户级线程,创建,切换,停止由Go语言操作。Go语言一次可创建上万协程。

线程:内核态,线程可以跑多个协程,栈MB级。切换,创建,停止都是很重的性能的操作。

协程的创建:在调用函数前使用go关键字。

Go语言推荐通过通信来实现共享内存

一个goroutine可以通过channel来发送值到另一个goroutine。 共享内存来实现通信也是可用的,但是会出现数据竞态影响性能。

Channel:通过make(chan 数据类型, [缓冲大小]) 来创建。不输入缓冲大小来创建无缓冲channel。

无缓冲通道会使发送和接收的goroutine同步化。

channel用例:

func CalSquare() {
   src := make(chan int)//创建通道
   dest := make(chan int, 3)//创建通道
   go func() {
      defer close(src)
      for i := 0; i < 10; i++ {
         src <- i //将i值通过channel传送到另一个方法
      }
   }()
   go func() {
      defer close(dest)
      for i := range src { //遍历i值
         dest <- i * i //传送到dest通道
      }
   }()
   for i := range dest { //遍历dest通道传送的值
      println(i)
   }
}

并发安全:

加锁通过对临界区的数据进行控制来实现线程安全

加锁:

var lock sync.Mutex

lock.Lock()
//其他操作
lock.Unlock()

WaitGroup:

WaitGroup.Add(int)//计数器+int

WaitGroup.Done()计数器-1

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

func ManyGo() {
   var wg sync.WaitGroup
   for i := 0; i < 5; i++ {
      wg.Add(1)
      go func(j int) {
         defer wg.Done()
         hello(j)
      }(i)
   }
   wg.Wait()
}

2: 依赖管理

GOPATH: Go语言环境变量。 两个项目不可以调用不同版本的pkg,无法实现pkg的多版本控制。

Go Vendor:通过每个项目引入不同版本的pkg的副本,解决依赖冲突。无法控制依赖的版本,更新项目可能出现依赖冲突

Go Module:官方推出的依赖管理系统,解决了前面的问题,通过 go mod/get来对依赖包进行管理

Go在对依赖版本的选择时会选择能够兼容的最低版本

依赖分发:

使用版本控制托管仓库:无法保证构建稳定性,无法保证依赖可用性,增加第三方压力。

go使用go proxy来分发依赖。go proxy缓存了不同版本的依赖,是稳定和可靠的依赖分发

proxy配置 GOPROXY="xxxx,xxxx,direct" direct为源站

go get example.org/pkg+@xxxx

update:默认

none:删除依赖,

v x.x.x: 特定依赖版本

xxxxxx:特定commit

master:分支的最新commit