Go语言进阶|青训营

89 阅读1分钟

Go语言进阶

Go routine

协程:用户态,轻量级线程

线程:内核态,线程跑多个协程

Go语言开启协程

只需要在调用函数时,在其前面加上关键字 go

go语言提倡通过通信共享内存,而不是通过共享内存(临界区)而实现通信

channel创建

make(chan 元素类型,[缓冲大小])

·有缓冲通道 make(chan int)

·无缓冲通道 make(chan int,2)

举例:

A子协程发送0-9数字,B协程计算输入数字的平方,主协程输出最后的平方数

package main
​
func CalSquare(){
  src:=make(chan int)
  dest:=make(chan int,3)
  go func(){//协程A
    defer close(src)
    for i:=0;i<10;i++{
      src<-i
    }
  }()
  go func(){//协程B
    defer close(dest)
    for i:=range src{
      dest<-i*i
    }
  }()//主协程
  for i:=range dest{
    println(i)
  }
}
​
func main(){
  CalSquare()
}

image-20230726163330752.png

并发安全性

通过对5个协程的并发执行,对协程不加锁,任由其对临界区自由执行,以及对临界区加锁,按顺序执行的比较示例:每个协程对变量执行2000+1此操作,用sleep设置时间延时

package main
​
import (
    "sync"
    "time"
)
​
var(
  x int64
  lock sync.Mutex
)
func addWithLock(){
  for i:=0;i<2000;i++{
    lock.Lock()
    x+=1
    lock.Unlock()
  }
}
func addWithoutLock(){
  for i:=0;i<2000;i++{
    x+=1
  }
}
func Add(){
  x=0
  for i:=0;i<5;i++{
    go addWithoutLock()
  }
  time.Sleep(time.Second)
  println("WithoutLock:",x)
  x=0
  for i:=0;i<5;i++{
    go addWithLock()
  }
  time.Sleep(time.Second)
  println("WithLock:",x)
}
​
func main(){
  Add()
}

image-20230726164200473.png

go语言通过WaitGroup可实现并发任务的同步,waitgroup有三个方法,Add,Done,Wait,Add(delta int)维护一个计数器,计数器+delta,Done计数器-1,wait实现阻塞直到计数器为0,计数器为0表示所有并发任务的完成

package main
​
import (
    "fmt"
    "sync"
)
​
func ManyGoWait(){
  var wg sync.WaitGroup
  wg.Add(5)
  for i:=0;i<5;i++{
    go func(j int){
      defer wg.Done()
      hello(j)
    }(i)
  }
  wg.Wait()//通过wait进行阻塞
}
func hello(i int){
  println("hello goroutine:"+fmt.Sprint(i))
}
func main(){
  ManyGoWait()
}

image-20230726165128715

依赖管理

依赖指各种安装包,工程项目不可能基于标准库0~1编码搭建,复杂项目可通过sdk引入相关依赖。

依赖管理方案

环境变量$GOPATH

项目代码直接依赖src下的代码

go get下载最新版本的包到src目录下

依赖管理的三要素
  1. 配置文件,描述依赖
  2. 中心仓库管理依赖库
  3. 本地工具
go vendor

项目目录下增加vendor文件,所有依赖包副本形式放在$ProjectRoot/vendor下

依赖寻址方式:vendor=>GOPATH

优点:通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题。

缺点:但是无法控制依赖的版本,更新项目又可能出现依赖冲突,导致编译出错

Go Module

通过go.mod文件管理依赖包版本

通过go get/go mod指令工具管理依赖包