这是我参与第五届青训营笔记创作活动的第2天
1. 语言进阶
- 并发VS并行
并发:多线程程序在一个核的cpu上运行
并行:多线程程序在多个核的cpu上运行
- 线程VS协程
线程:用户态,轻量级线程,栈MB级别
协程:内核态,线程跑多个协程,栈KB级别
Goroutine快速打印hello goroutine
package main
import (
"fmt"
"time"
)
func hello(i int) {
println("hello goroutine: " + fmt.Sprint(i))
}
func main() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
channelmake(chan, 元素类型, [缓冲大小])- 无缓冲通道
make(chan, int) - 有缓存通道
make(chan, int, 3)
代码示例
A子协程发送数字0~9
B子协程计算输入数字的平方
主协程输出最后的平方数
package main import "fmt" func test() { 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 { fmt.Printf("i: %v\n", i) } } func main() { test() }- 无缓冲通道
- 并发安全
lock
对变量进行2000次加1操作, 5个协程并发执行
package main
import (
"fmt"
"sync"
"time"
)
var (
x int64
lock sync.Mutex
)
func addWithLock() {
for i := 0; i < 2000; i++ {
lock.Lock()
x += 1
lock.Unlock()
}
}
func addWithoutLock() {
for i := 0; i < 2000; i++ {
x += 1
}
}
func add() {
x = 0
for i := 0; i < 5; i++ {
go addWithLock()
}
time.Sleep(time.Second)
fmt.Printf("x: %v\n", x)
x = 0
for i := 0; i < 5; i++ {
go addWithoutLock()
}
time.Sleep(time.Second)
fmt.Printf("x: %v\n", x)
}
func main() {
add()
}
2. 模块管理
- 工具
go mod
go mod init初始化,创建go.mod文件
go mod download下载模块到本地缓存
go mod tidy增加需要的依赖,删除不需要的依赖
- 依赖管理三要素
- 配置文件,描述依赖
- 中心仓库管理依赖库
- 本地工具
3. 测试
- 单元测试-规则
- 所有测试文件以
_test.go结尾func TestXxx(*testing.T)- 初始化逻辑放到
TestMain种
- 基准测试
- 优化代码,需要对当前代码分析
- 内置的测试框架提供了基准测试的能力