Go进阶与测试 | 青训营笔记

123 阅读3分钟

Gorotine

无缓冲的信道在取消息和存消息的时候都会挂起当前的 goroutine,除非另一端已经准备好。如果不用信道来阻塞主线的话,主线程就会过早跑完,其他线程都没有机会执行。 无缓冲的信道永远不会存储数据,只负责数据的流通。体现在:

  1. 从无缓冲信道取数据,必须要有数据流进来才可以,否则当前线阻塞
  2. 数据流入无缓冲信道, 如果没有其他 goroutine 来拿走这个数据,那么当前线阻塞

Channel

Actor模型和CSP模型区别

Actor 之间直接通讯,而 CSP 是通过 Channel 通讯,在耦合度上两者是有区别的,后者更加松耦合。

主要的区别在于:CSP 模型中消息的发送者和接收者之间通过 Channel 松耦合,发送者不知道自己消息被哪个接收者消费了,接收者也不知道是哪个发送者发送的消息。在 Actor 模型中,由于 Actor 可以根据自己的状态选择处理哪个传入消息,自主性可控性更好些。

在 Go 语言中为了不堵塞进程,程序员必须检查不同的传入消息,以便预见确保正确的顺序。CSP 好处是 Channel 不需要缓冲消息,而 Actor 理论上需要一个无限大小的邮箱作为消息缓冲。

CSP 模型的消息发送方只能在接收方准备好接收消息时才能发送消息。相反,Actor 模型中的消息传递是异步 的,即消息的发送和接收无需在同一时间进行,发送方可以在接收方准备好接收消息前将消息发送出去。

make(chan int) //创建一个无缓冲的Channel
make(chan int, 100) //创建一个有缓冲的Channel

Mock

通过模拟请求,减少测试环境对其他文件的依赖

package main

import (
   "bou.ke/monkey"
   "github.com/stretchr/testify/assert"
   "testing"
)
func a() int {
   return 1
}
func hello() int{
   out:=a()
   return out
}
func TestMock(t *testing.T) {
   monkey.Patch(a,func()int{return 2})  //把a函数mock成返回值为2的函数
   defer monkey.Unpatch(a)
   out := hello()
   assert.Equal(t,2,out)
}

终端运行指令:

go test temp_test.go -gcflags "all=-N -l"

直接点击运行的话patch不生效

基准测试

基准测试以Benchmark为前缀,需要一个testing.B类型的参数b,基准测试必须要 *执行b.N**次,这样的测试才有对照性,b.N的值是系统根据实际情况去调整的,从而保证测试的稳定性。

package main

import "math/rand"

var ServerIndex [10]int

func InitServerIndex() {
   for i := 0; i < 10; i++ {
      ServerIndex[i] = i + 100
   }
}
func Select() int {
   return ServerIndex[rand.Intn(10)]
}
func main() {

}

//test文件
package main

import (
   "testing"
)

func BenchmarkSelect(b *testing.B) {
   InitServerIndex()
   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()
      }
   })
}

终端运行指令:

go test temp_test.go temp.go -bench=.* -benchmem

不加.* -benchmem不给生效,不知道什么原因

执行结果:

goos: windows
goarch: amd64
BenchmarkSelect-8               58084939                19.5 ns/op         
BenchmarkSelectParallel-8       17853555                65.1 ns/op         
PASS
ok      command-line-arguments  2.989s

第二列很大的数字是测试的次数

第三列 19.5 ns/op表示每一个操作耗费多少时间(纳秒) (即BenchmarkSelect函数进行了58084939次,每次求和花费了19.5 ns)

可以用fastrand替换rand提高性能