并发VS并行
- 并发指多线程程序在一个核的cpu上运行
- 并行指多线程程序在多个核的cpu上运行 Go语言可以充分发挥多核优势,高效并行
Goroutine
协程:用户态,轻量级线程,栈kb级别
线程:内核态,线程跑多个协程,栈mb级别
快速打印hello goroutine
package main
import (
"fmt"
"time"
)
func hello(i int) {
println("hello goroutine :" + fmt.Sprint(i))
}
func HelloGoroutine() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
func main() {
HelloGoroutine()
}
/*
hello goroutine :0
hello goroutine :4
hello goroutine :3
hello goroutine :2
hello goroutine :1
*/
CSP(Communicating Sequential processes)
提倡通过通信共享内存而不是共享内存实现通信,也就是提倡使用管道
Channel
make(chan 元素类型,[缓冲大小])
- 无缓冲通道 make(chan int)
- 有缓冲通道 make(chan int ,2)
带缓存的Channel可以解决由于生产,消费者速度不同带来的问题
package 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
}
}()
go func() {
defer close(dest)
for i := range src {
dest <- i * i
}
}()
for i := range dest {
println(i)
}
}
/*0
1
4
9
16
25
36
49
64
81
*/
并发安全 Lock
package main
import (
"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 addWithoutLock()
}
time.Sleep(time.Second)
println("WithoutLock:", x)
x = 0
for i := 0; i < 5; i++ {
go addWithLock()
}
time.Sleep(time.Second)
println("WithLock:", x)
}
func main() {
Add()
}
/*
WithoutLock: 8898
WithLock: 10000
*/
WaitGroup
package main
import "sync"
func hello(i int) {
println(i)
}
func ManyGowWait() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
func main() {
ManyGowWait()
}
/*
0
2
3
4
1
*/
依赖管理
- 工程项目不可能基于标准库0~1编码搭建
- 管理依赖库
Go 依赖管理演进
GOPATH->GO Vendor->Go Module
- 不同环境(项目)依赖的版本不同
GoPATH
GOPATH路径应有bin,pkg,src文件夹
- bin保存项目编译的二进制文件
- pkg保存项目编译的中间产物,加速编译
- src保存项目源码
GoPATH-弊端
假如项目A和B依赖于某一个package的不同版本,package无法实现多版本控制
Go Vendor
- 项目目录下增加vendor文件,所有依赖包的副本形式放在$ProjectRoot/vendor
- 依赖寻址方式:vendor ->GOPATH
Go Vendor-弊端
一旦版本更新可能导致不兼容
Go Module
- 通过go.mod文件管理依赖包版本
- 通过go get/go mod 指令工具管理依赖包
- 定义版本规则和项目的依赖关系
依赖管理三要素
- 配置文件,描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod
依赖配置- go.mod
module test//依赖管理单元
go 1.19 //原生库
require (//单元依赖
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.8.2 // indirect
github.com/go-oauth2/oauth2/v4 v4.5.2 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.1 // indirect
github.com/go-session/session v3.1.2+incompatible // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/goccy/go-json v0.9.11 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/protobuf v1.5.3 // indirect)
依赖配置-version
语义化版本
- {MINOR}.${PATCH} 基于commit伪版本 vx.0.0-yyyymmddhhmmss-abcdefgh1234 第一部分类似版本好,第二部分为提交时间,第三为哈希码前12位
依赖配置-indirect
module test//依赖管理单元
go 1.19 //原生库
require (//单元依赖
github.com/gin-contrib/sse v0.1.0 // indirect <-此为间接引用
github.com/gin-gonic/gin v1.8.2 // indirect
github.com/go-oauth2/oauth2/v4 v4.5.2 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.1 // indirect
github.com/go-session/session v3.1.2+incompatible // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/goccy/go-json v0.9.11 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/protobuf v1.5.3 // indirect)
依赖配置-incompatible
module test//依赖管理单元
go 1.19 //原生库
require (//单元依赖
github.com/gin-contrib/sse v0.1.0 // indirect <-此为间接引用
github.com/gin-gonic/gin v1.8.2 // indirect
github.com/go-oauth2/oauth2/v4 v4.5.2 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.1 // indirect
github.com/go-session/session v3.1.2+incompatible // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/goccy/go-json v0.9.11 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible <-主版本2+模块会在模块路径增加/vN后缀 // indirect
github.com/golang/protobuf v1.5.3 // indirect)
依赖配置 兼容
在编译时会使用最低兼容度的版本
依赖分发-回源
如果使用第三方仓库会导致很多问题,比如:原作者修改,删除代码,平台压力过大删除
依赖分发-Proxy
proxy会缓存网站内容,使其稳定可靠
依赖分发- 变量 GOPROXY
当需要依赖时,先从PROXY1获取,再从PROXY2获取,直到全部获取并且都失败,从源站点获取
工具- go get
go get example.org/pkg
- @update 默认
- @none 删除依赖
- @v1.1.2 tag版本,语义版本
- @23dfdd5 特定的commit
- @master 分支的最新commit
工具- go mod
go mod
- init 初始化,创建go.mod文件
- download 下载模块到本地缓存
- tidy 增加需要的依赖,删除不需要的依赖
小结
主要学习了GO的协程与线程和依赖管理工具的使用