这是我参与「第五届青训营 」伴学笔记创作活动的第2天
1.go语言进阶
Go可以充分发挥多核性能
1.1 Goroutine
协程:用户态,轻量级线程,栈mb级别
线程:内核态,线程跑多个协程,栈kb级别
例子:
package main
import (
"fmt"
"time"
)
func hello(i int) {
fmt.Println("routine:", i)
}
func main() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second) //防止主协程退出
}
运行结果:
routine: 4
routine: 3
routine: 2
routine: 0
routine: 1
1.2 CSP
go内部俩机制都有,推崇前一种
1.3 Channel
make(chan type,[size])
- [size]代表有无缓冲通道
例子(通信实现共享内存):
package main
import "fmt"
func main() {
src := make(chan int)
dest := make(chan int,3)
go func() {
defer close(src)
for i := 0; i < 5; i++ {
src <- i
fmt.Println("src<-", i)
}
}()
go func() {
defer close(dest)
for i := range src { //有数据传就一直接收
dest <- i * i
fmt.Println("dest<-", i*i)
}
}()
for i := range dest { //有数据传就一直接收
fmt.Println(i)
}
}
运行结果:
src<- 0
dest<- 0
src<- 1
0
1
dest<- 1
dest<- 4
4
src<- 2
src<- 3
dest<- 9
src<- 4
9
16
dest<- 16
(print函数会有部分延迟)
1.4 并发安全Lock
对临界区访问时需要加锁
为什么会少加?
猜测:协程1和协程2同时拿到相同值x,向x地址写入x+1,这就会导致本来+2的现在只+1
1.5 WaitGroup
可以替代之前time.Sleep的操作,让主协程等待子协程全部执行完之后再结束
内部是一个计数器
例子:
对1.1例子进行改造,将time.sleep替换为waitgroup
package main
import (
"fmt"
"sync"
)
func hello(i int) {
fmt.Println("routine:", i)
}
func main() {
var wg sync.WaitGroup //+
wg.Add(5)//+
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
wg.Done()//+
}(i)
}
wg.Wait()//+
}
2.依赖管理
2.1 go依赖管理发展历程
Gopath->go vender->go module
1.Gopath
缺点:无法实现包的多版本控制
2.go vender
相当于保存多个依赖文件
缺点:
底层包版本不同
3.go module
2.2 依赖管理三要素
类似maven
| 1.配置文件,描述依赖 | go.mod |
|---|---|
| 2.中心仓库管理依赖库 | Proxy |
| 3.本地工具 | go get/go mod |
2.3 go.mod
版本规则:
- majar是大版本,可以不兼容,minor是新增函数或功能,需要兼容,patch一般是修复bug
依赖-indirect:
indirect=间接依赖
依赖-incompitable
可能存在不兼容的代码逻辑
题:
选B,对于go来说,会选择较高的兼容版本
2.4 Proxy
一个稳定的依赖服务站点,在proxy上面下载的依赖稳定可靠
配置goproxy