这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
Goroutine
go语言实现了更加轻量的协程。
- 线程 MB级别
- 协程 KB级别
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
CSP(Communicating Sequential Processes)
用于描述两个并发的实体通过共享的通讯管道(channel)进行通信的 并发模型
channel
通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。
ch <- v // 把 v 发送到通道 ch
v := <-ch // 从 ch 接收数据
// 并把值赋给 v
package main
import "fmt"
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum // 把 sum 发送到通道 c
}
func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <-c, <-c // 从通道 c 中接收
fmt.Println(x, y, x+y)
}
并发安全
go 中有两种锁,为 sync.Mutex 和 sync.RWMutex。
-
sync.Mutex的锁只有一种锁:Lock(),它是绝对锁,同一时间只能有一个锁。 -
sync.RWMutex叫读写锁,它有两种锁:RLock()和Lock():-
RLock()叫读锁。它不是绝对锁,可以有多个读者同时获取此锁(调用mu.RLock)。 -
Lock()叫写锁,它是个绝对锁,就是说,如果一旦某人拿到了这个锁,别人就不能再获取此锁了。
-
package main
import (
"fmt"
"sync"
"time"
)
var (
x int64
l sync.RWMutex
)
func addWithLock(){
for i:=0;i<2000;i++{
l.Lock()
x+=1
l.Unlock()
}
}
func addWithoutLock(){
for i:=0;i<2000;i++{
x+=1
}
}
func main(){
x =0
for i:=0;i<5;i++{
go addWithLock()
}
time.Sleep(time.Second)
fmt.Println("withLock",x)
x=0
for i:=0;i<5;i++{
go addWithoutLock()
}
time.Sleep(time.Second)
fmt.Println("withoutLock",x)
}
语言等待组
Go语言中除了可以使用通道(channel)和互斥锁进行两个并发程序间的同步外,还可以使用等待组进行多个任务的同步,等待组可以保证在并发环境中完成指定数量的任务
在 sync.WaitGroup(等待组)类型中,每个 sync.WaitGroup 值在内部维护着一个计数,此计数的初始默认值为零。
等待组有下面几个方法可用,如下表所示。
Add(delta int) 等待组的计数器 +1
Done() 等待组的计数器 -1
Wait() 当等待组计数器不等于 0 时阻塞直到变 0。
package main
import (
"fmt"
"sync"
)
func main(){
var wg sync.WaitGroup
wg.Add(5)
for i:=0;i<5;i++{
go func (j int){
fmt.Println(j)
wg.Done()
}(i)
}
wg.Wait()
}
依赖管理
go语言依赖管理的演进
GOPATH弊端:不同项目不能依赖同一个库的不同版本
GO Vendor弊端:不能很清晰的标识依赖的版本概念
go module 是Go语言从 1.11 版本之后官方推出的版本管理工具,并且从 Go1.13 版本开始,go module 成为了Go语言默认的依赖管理工具
- 通过go.mod文件管理依赖包版本(配置文件,描述依赖)
- 通过go get/go mod指定工具管理依赖包
- 通过Proxy对依赖进行分发
依赖管理三要素
依赖分发
当依赖分发的时候,可能由于第三方的修改删除造成的代码变动给给我们带来不便,而同时我们也会增加第三方的压力。
我们使用Proxy就可以很好的解决这个问题
依赖工具
测试
从上到下,覆盖率逐渐变大,成本却逐渐变低