testing框架会将xxx_test.go的文件引入,调用所有TestXxx的函数
在cal_test.go文件里面写这个
package main
import "testing"
func TestAdd(t *testing.T) {
a, b := 1, 2
if add(a, b) != 4 {
t.Fatalf("Wrong Answer!")
}
}
在cal.go文件里写这个
package main
func add(a int, b int) int {
return a + b
}
运行go test -v的命令,就能运行单测
可以得到结果
=== RUN TestAdd
cal_test.go:8: Wrong Answer!
--- FAIL: TestAdd (0.00s)
testing框架import这个test文件之后,会调用所有TestXxx的函数,注意大写!
主线程类似进程
协程类似线程,是轻量级的线程
协程的特点
import (
"fmt"
"strconv"
"time"
)
func test() {
for i := 0; i < 5; i++ {
fmt.Println("test() calls! " + strconv.Itoa(i))
time.Sleep(time.Second)
}
}
func main() {
go test()
for i := 0; i < 5; i++ {
fmt.Println("main() calls! " + strconv.Itoa(i))
time.Sleep(time.Second)
}
}
输出
main() calls! 0
test() calls! 0
test() calls! 1
main() calls! 1
main() calls! 2
test() calls! 2
test() calls! 3
main() calls! 3
main() calls! 4
test() calls! 4
go关键字会另起一个协程,主线程执行到这里会开一个协程并行执行,如果主线程执行完毕退出,协程会被强制退出
M(Machine)是操作系统的主线程,也就是物理线程
P(Processor)协程执行的上下文
G(Gorountine)协程
Go语言的协程是轻量级的,是逻辑态的,可以起上万个协程;而C/java的多线程是内核态的,几千个就会耗光CPU
runtime.NumCPU()
//获取本地CPU数目
runtime.GOMAXPROCS(int)
//设置GO最大可用的CPU数目
//Go Max Processors
多个协程同时访问一个资源会发生冲突,会发生并发问题
在java中我们有锁和原子类来保证并发安全
声明一个全局锁变量lock
lock sync.Mutex
//sync是同步的意思,Muti-excluded互斥锁?
lock.Lock()//在进行并发的读写操作的时候,先上个锁
...//在进行操作的时候,别的协程会排队等待
lock.Unlock()//解锁之后,才能给别的协程使用
主线程读的时候也需要加锁,因为底层不知道协程已经解锁了,会发生资源冲突
但是这样不同协程之间没办法通讯,不知道什么时候协成完成任务了,白白空转浪费时间,或者提前结束主线程,终止协程,管道可能能解决这些问题,明天再学