这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天
语言进阶
介绍
并发:多线程程序在一个核的cpu上运行
并行:多线程程序在多个核的cpu上运行
Go可以充分发挥多核优势,高效运行
Go语言一次可以创建上万个协程
Goruotine是协程
只需要在一个函数前面加上 go 关键词,就可以让这个函数以一个协程来运行
package main
import (
"fmt"
"time"
)
func printhello(i int) {
fmt.Println("hello goroutine:", i)
}
func main() {
for i := 0; i < 5; i++ {
go func(j int) {
printhello(j)
}(i) //这个i传递给上面的j
}
time.Sleep(time.Second) //time.Second是1秒,这个设置来是保证子协程在执行完之前主线程不至于退出
}
提倡通过通信共享内存而不是共享内存而实现通信
通过通信共享内存:Gorountine1通过通道传输值给另一个Gorountine2
通过共享内存实现通信:要有互斥量,对临界区加锁。
channel
创建:make(chan 元素类型,[缓冲大小])
- 无缓冲通道 make(chan int),发送的gorountine和接受的gorountine同步化,又称同步通道
- 有缓冲通道 make(chan int, 2),2代表缓冲区的容量
有缓冲是因为消费者与生产者速度不同。这样不会因为消费者速度过低而影响生产者高速生产。
A 子协程发送0~9数字
B 子协程计算输入数字的平方
主协程输出最后的平方数
package main
import "fmt"
func main() {
src := make(chan int)
dest := make(chan int, 3)//有缓冲是因为消费者与生产者速度不同。(下面有输出)
//A
go func() {
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
}()
//B
go func() {
defer close(dest)
for i := range src {
dest <- i * i
}
}()
//主
for i := range dest {
fmt.Println(i)
}
}
并发安全 Lock
记得要time.Sleep(time.Second),等子协程做完,不然会出错。
有了锁,这样就不会变量冲突。
package main
import (
"fmt"
"sync"
"time"
)
var x int
var lock sync.Mutex
func addWithLock() {
for i := 0; i < 2000; i++ {
lock.Lock()
x++
lock.Unlock()
}
}
func addWithoutLock() {
for i := 0; i < 2000; i++ {
x++
}
}
func main() {
x = 0
for i := 0; i < 5; i++ {
go addWithLock()
}
time.Sleep(time.Second)
fmt.Println("WithLock x:", x)
x = 0
for i := 0; i < 5; i++ {
go addWithoutLock()
}
time.Sleep(time.Second)
fmt.Println("WithoutLock x:", x)
}
/*
WithLock x: 10000
WithoutLock x: 8116
*/
WaitGroup
另一种方法
func main() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
printhello(j)
}(i)
}
wg.Wait()//主协程阻塞直到计数器为0
}
依赖管理
Go Module
- 通过go.mod文件管理依赖包版本
- 通过go get/go mod指令工具管理依赖包
终极目标:定义版本规则和管理项目依赖关系
依赖管理三要素
- 配置文件,描述依赖
go.mod - 中心仓库管理依赖库
Proxy - 本地工具 `go get / go mod
go.mod文件,间接依赖会用//indirect标识
版本比较老的就没有go.mod文件
不能直接用github这样代码托管平台作为依赖,有可能被修改删除;负载大
工具 - go get
go get example.org/pkg
@update默认@none删除依赖@v1.1.2tag版本,语义版本@23dfdd5特定的commit提交@master分支的最新commit
工具 - go mod
go mod
init初始化,创建go.mod文件download下载模块到本地缓存tidy增加需要的依赖,删除不需要的依赖