Go 语言进阶 | 青训营

375 阅读1分钟

Go 语言进阶

并发 vs 并行

协程 - 用户态、轻量级线程,栈 KB 级别

线程 - 内核态、线程跑多协程、栈 MB 级别

CSP

提倡通过通信共享内存(通道)而非直接共享内存(临界区)

Channel

make(chan <type>, [size])

无缓冲通道

有缓冲通道

src := make(chan int)
dest := make(chan int, 3)

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()

lock.Unlock()

j := 0
var lock sync.Mutex
for i := 0; i < 5; i++ {
    go func() {
        for i := 0; i < 1000; i++ {
            lock.Lock()
            j++
            lock.Unlock()
        }
    }()
}
time.Sleep(time.Second)
println("add with lock", j)

依赖管理

Go依赖演进

GOPATH

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

Go Vendor

项目目录内实现vendor目录

Go Module

通过go.mod管理依赖包

依赖管理要素

配置文件

go.mod

中心仓库

proxy

本地工具

go get & go mod

语义化版本

${MAJOR}.${MINOR}.${PATCH}

commit版本

vx.0.0-yyyymmddhhmmss-abcdefgh1234

依赖配置

module XXX

go X.X

require (
	example/lib v1.1.1
)

依赖分发-回源

依赖分发-变量 GOPROXY

从proxy直至源站获取依赖

测试

单元测试

  1. 规则

测试文件以_test.go结尾

测试函数以Test开头

初始化逻辑置于TestMain函数内

  1. 示例
package Go

import (
	"github.com/stretchr/testify/assert"
	"os"
	"testing"
)

func TestDemo(t *testing.T) {
	output := 1 + 1
	expectOutput := 2
	assert.Equal(t, output, expectOutput)
}

func TestMain(m *testing.M) {
	code := m.Run()

	os.Exit(code)
}
  1. 运行

go test [flags] [packages]

  1. assert

assert.Equal(t, output, expectOutput)

参见 github.com/stretchr/testify/assert

  1. 覆盖率

一般覆盖率在50%-60%左右,较高覆盖率80%+

测试分支相互独立,全面覆盖

测试单元粒度足够小,函数单一职责

import (
    "github.com/stretchr/testify/assert"
    "os"
    "testing"
)

func TestDemo(t *testing.T) {
    output := 1 + 1
    expectOutput := 2
    assert.Equal(t, output, expectOutput)
}

func TestMain(m *testing.M) {
    code := m.Run()

    os.Exit(code)
}

Mock测试

  1. 依赖

File、DB、Cache

外部依赖 - 稳定&幂等

  1. 文件

文件使用

  1. mock

为函数or方法打桩

patch -> test -> unpatch

基准测试

测试代码的性能