Go 语言进阶与依赖管理与测试 | 青训营笔记

98 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天 主要有3个方面的内容:

  • go进阶知识
  • go 包管理
  • go 测试

这三个方面一直是了解个大概,借此机会从课堂好好学学。

go进阶

go 使用goroutine并发执行程序,goroutine初始大小为 2-8kb,具体与go版本与操作系统版本有关。 go并发3大利器:channel、sync.Mutex、sync.WaitGroup

channel

如何优雅的从channel循环取值

  1. 接收值判断通道是否关闭
  2. 使用 for range

通道使用异常情况:

  • Channel 满或者nil 阻塞
  • channel 为空或者nil 阻塞
  • 关闭已关闭的channel panic
  • 已关闭的channel panic
  • 已关闭channel 返回零值
func main() {
   ch1 := make(chan int)
   ch2 := make(chan int)

   // 向ch1发送数据
   go func() {
      for i := 0; i < 100; i++ {
         ch1 <- i
      }
      close(ch1)
   }()

   // 从ch1读值,再写入ch2
   go func() {
      for {
         i, ok := <-ch1 //通道关闭后ok为false
         if !ok {
            break
         }
         ch2 <- i
      }
      close(ch2)
   }()

   //从ch2接收值打印
   for i := range ch2 { // 通道关闭后自动退出range循环
      fmt.Println(i)
   }
}

sync.Mutex的简单使用

var mu sync.Mutex

mu.Lock()  // 加锁
do something  // 临界资源
mu.Unlock()  // 解锁

sync.WaitGroup的同步操作简单使用

var wg sync.WaitGroup
wg.Add(10)  // 初始化并发任务数为10
go func() {
    do something
    wg.Done()  // 每当1个协程完成操作任务数减1
}
wg.Wait()  // 主程序阻塞至所有任务完成

go 包管理

go 依赖演进

1. GOPATH

使用环境变量 $GOPATH

 --$GOPATH    
 --bin 编译后的二进制文件
 --pkg 编译的中间产物
 --src 源码

项目直接依赖src下源码、无法依赖某package不同版本

2. GO Vendor

使用一个副本文件夹Vvendor替换$GOPATH存储packages 但依旧无法控制依赖的版本,更新项目时容易产生依赖冲突

3. GO Module

通过 go.mod 文件管理依赖版本 go mod init、 go mod tidy、go get

go 单元测试

Go 语言推荐测试文件和源代码文件放在一块,测试文件以 _test.go 结尾。比如,当前 package 有 calc.go 一个文件,我们想测试 calc.go 中的 Add 和 Mul 函数,那么应该新建 calc_test.go 作为测试文件。

example/
   |--calc.go
   |--calc_test.go

源码

package main

func Add(a int, b int) int {
    return a + b
}

func Mul(a int, b int) int {
    return a * b
}

测试

package main

import "testing"

func TestAdd(t *testing.T) {
	if ans := Add(1, 2); ans != 3 {
		t.Errorf("1 + 2 expected be 3, but %d got", ans)
	}

	if ans := Add(-10, -20); ans != -30 {
		t.Errorf("-10 + -20 expected be -30, but %d got", ans)
	}
}

go test 自动执行当前目录下所有测试