GO语言进阶|青训营笔记

344 阅读2分钟

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


theme: github highlight: a11y-dark

语言进阶

Goroutine


func c(i int) {
	fmt.Println(i)
}
func main() {

	for i := 0; i < 5; i++ {
		go func(j int) {
			c(j)
		}(i)
	}
	//不能不sleep 否则main执行完就直接退出了 无法输出
	time.Sleep(time.Second)
}

Channel

make(chan 元素类型,[缓冲大小]) 不给出缓冲大小:无缓冲通道 给出:有缓冲通道

使用:


func main() {
	src := make(chan int)
	dest := make(chan int, 3)

	go func() {
		defer close(src)
		for i := 0; i < 10; i++ {
			//这里是往src中放
			src <- i
		}
	}()

	go func() {
		defer close(dest)
		// i是从src中取出来的值
		for i := range src {
			//放入修改后的值
			dest <- i * i
		}
	}()

	// 进程2放入dest 主进程从dest中取
	for i := range dest {
		fmt.Println(i)
	}

}

Lock

两种实现并发安全计数的方式

通过互斥锁锁住临界区

package main

import (
	"fmt"
	"sync"
	"time"
)

var (
	//全局x
	x int64
	//注意要定义lock
	lock sync.Mutex
)

func addWithLock() {
	for i := 0; i < 2000; i++ {
		lock.Lock()
		x += 1
		lock.Unlock()
	}
}
func main() {

	for i := 0; i < 5; i++ {
		go addWithLock()
	}
	//别忘了sleep 否则main执行完就退出
	time.Sleep(time.Second)
	fmt.Println(x)
}

WaitGroup

通过WaitGroup实例,Add申请计数器,Done对计数器-1,计数器为0时,Wait操作才会停止阻塞,放行

package main

import (
	"fmt"
	"sync"
)

func main() {
	//不加的话 main执行完就退出了
	var wg sync.WaitGroup

	wg.Add(5)
	for i := 0; i < 5; i++ {
		go func(j int) {
			defer wg.Done()
			fmt.Println(j)
		}(i)
	}
	wg.Wait()
}

Go依赖管理

Go Module

三要素 go.mod

Proxy :GOPROXY

go get

go mod

测试

单元测试

  • 文件命名:xxx_test.go

  • 测试文件中方法命名:Test方法名(t *testing.T){}

  • 执行测试时,测试前测试后的前置收尾工作放到TestMain方法中

  • 执行测试:go test或者go test -v -v表示更详细

  • 只有执行之后 在vscode才有方法左侧的三角执行按钮

func TestCalSquare(t *testing.T) {
	CalSquare()
}

func TestMain(m *testing.M) {

	fmt.Println("before test......")
	//执行写的test方法
	m.Run()
	fmt.Println("after test......")

}

覆盖率

go test xxxx_test.go xxx.go -cover

单元测试覆盖率,使用--cover参数

Mock(模拟数据)

原本测试:从一个文件中读入

log文件:

line11
line22
line33
line44
line55

//方法
func ReadFirstLine() string {
	open, err := os.Open("log")
	defer open.Close()
	if err != nil {
		return ""
	}
	sanner := bufio.NewScanner(open)
	for sanner.Scan() {
		return sanner.Text()
	}
	return ""
}


//测试方法
func TestProcessFirstLineWithMock(t *testing.T) {
	firstLine := ReadFirstLine()
	assert.Equal(t, "line00", firstLine)
}

现在:

func TestProcessFirstLineWithMock(t *testing.T) {
	//替换ReadFirstLine方法
	//原本ReadFirstLine是从文件中读 现在是给一个函数返回
	monkey.Patch(ReadFirstLine, func() string {
		return "line110"
	})
	//还原
	defer monkey.Unpatch(ReadFirstLine)
	line := ProcessFirstLine()
	assert.Equal(t, "line000", line)
}

基准测试

基准测试的目的是测试运行的性能

go test -bench=. 不要忘记最后面的点

执行结果:

func BenchmarkSelect(b *testing.B) {
	InitServerIndex()
        //resettime
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		Select()
	}
}
func BenchmarkSelectParallel(b *testing.B) {
	InitServerIndex()
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			Select()
		}
	})
}
func BenchmarkFastSelectParallel(b *testing.B) {
	InitServerIndex()
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			FastSelect()
		}
	})
}
goarch: amd64
pkg: github.com/Moonlight-Zhao/go-project-example/benchmark
cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
BenchmarkSelect-4                       44696738                27.50 ns/op
BenchmarkSelectParallel-4               23511862                57.66 ns/op
BenchmarkFastSelectParallel-4           237921783                5.447 ns/op
PASS
ok      github.com/Moonlight-Zhao/go-project-example/benchmark  6.468s

课后作业