这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
1: Go的高性能本质
Go语言通过并发性能极高的调动模型实现最大限度的资源利用,充分发挥多核计算机的性能优势。
协程:用户态,轻量级线程,栈KB级。轻量级,用户级线程,创建,切换,停止由Go语言操作。Go语言一次可创建上万协程。
线程:内核态,线程可以跑多个协程,栈MB级。切换,创建,停止都是很重的性能的操作。
协程的创建:在调用函数前使用go关键字。
Go语言推荐通过通信来实现共享内存
一个goroutine可以通过channel来发送值到另一个goroutine。 共享内存来实现通信也是可用的,但是会出现数据竞态影响性能。
Channel:通过make(chan 数据类型, [缓冲大小]) 来创建。不输入缓冲大小来创建无缓冲channel。
无缓冲通道会使发送和接收的goroutine同步化。
channel用例:
func CalSquare() {
src := make(chan int)//创建通道
dest := make(chan int, 3)//创建通道
go func() {
defer close(src)
for i := 0; i < 10; i++ {
src <- i //将i值通过channel传送到另一个方法
}
}()
go func() {
defer close(dest)
for i := range src { //遍历i值
dest <- i * i //传送到dest通道
}
}()
for i := range dest { //遍历dest通道传送的值
println(i)
}
}
并发安全:
加锁通过对临界区的数据进行控制来实现线程安全
加锁:
var lock sync.Mutex
lock.Lock()
//其他操作
lock.Unlock()
WaitGroup:
WaitGroup.Add(int)//计数器+int
WaitGroup.Done()计数器-1
WaitGroup.Wait()//阻塞直到计数器为0
func ManyGo() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
2: 依赖管理
GOPATH: Go语言环境变量。 两个项目不可以调用不同版本的pkg,无法实现pkg的多版本控制。
Go Vendor:通过每个项目引入不同版本的pkg的副本,解决依赖冲突。无法控制依赖的版本,更新项目可能出现依赖冲突
Go Module:官方推出的依赖管理系统,解决了前面的问题,通过 go mod/get来对依赖包进行管理
Go在对依赖版本的选择时会选择能够兼容的最低版本
依赖分发:
使用版本控制托管仓库:无法保证构建稳定性,无法保证依赖可用性,增加第三方压力。
go使用go proxy来分发依赖。go proxy缓存了不同版本的依赖,是稳定和可靠的依赖分发
proxy配置
GOPROXY="xxxx,xxxx,direct" direct为源站
go get example.org/pkg+@xxxx
update:默认
none:删除依赖,
v x.x.x: 特定依赖版本
xxxxxx:特定commit
master:分支的最新commit