go语言进阶 | 青训营笔记

103 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

并发编程

goroutine

作为低开销的携程,用户态的goroutine可以被内核态的线程创建出来,体量很小,大小从2KB-2GB,同时内核态的线程就可以对应到GMP模型中的M。

channel

go语言提倡通过通信共享内存而不是通过共享内存实现通信

channel可分为有缓冲通道无缓冲通道

无缓冲通道在被传入时没有被另一goroutine及时读取会引起panic

并发安全sync.Mutex包

Lock()Unlock()对临界区资源加锁解锁

WaitGroup

Add()Done()Wait()

waitgroup内部维护了一个计时器,每起一个goroutine使计数器+1,执行结束计数器-1;住携程阻塞知道计数器为0

依赖管理

go Vendor

  • 项目目录下增加vendor文件,所有依赖包副本形式放在$projectRoot/vendor
  • 依赖寻址方式:vendor => GOPATH

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

感觉和go mod的理念很像?

go mod

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

为项目开启go mod

go mod init projectname

indirect标识该包为间接依赖包

go mod tidy下载项目需要的依赖,删除不需要的依赖

测试

规则

  • 所有测试文件以_test.go结尾
  • func TestXxx(*testing.T)
  • 初始化逻辑放到TestMain中
func TestMain(m *testing.M)   {
  //测试前:数据装在、配置初始化等前置工作
  code:=m.Run()
  //测试后:释放资源等收尾工作
  os.Exit(code)
}

基准测试

func BenchmarkSprintf(b *testing.B){
  num:=10
  b.ResetTimer()
  for i:=0;i<b.N;i++{
     fmt.Sprintf("%d",num)
  }
}
  • b.ResetTimer是重置计时器,这样可以避免for循环之前的初始化代码的干扰
➜  go test -bench=. -run=none
BenchmarkSprintf-8      20000000               117 ns/op
PASS
ok      flysnow.org/hello       2.474s
  • -8代表运行时对应的gomaxprocs
  • 20000000代表for次数
  • 117 ns/op代表每次会花费117ns