01.语言进阶(并发编程)
goroutine
协程: 用户态,轻量级线程,栈KB级别
线程: 内核态,线程跑多个协程,栈MB级别
- goroutine 是 Go 语言中并发执行的基本单位,它是一种用户态的轻量级线程。
- 通过使用 go 关键字,可以在 Go 语言中创建 goroutine。使用匿名函数或有名函数作为 goroutine 的执行体。
// 匿名函数
go func() {
// goroutine 执行的代码
}()
// 有名函数
func test(){
fmt.Printf("golang tutorial\n")
}
go test()
- goroutine 的调度是由 Go 运行时进行管理的,它可以在多个线程上并发执行。
- goroutine 的创建和销毁开销相对较小,可以快速启动和切换,因此适用于高并发的场景。
channel
- 通道(channel)是用来传递数据的一种数据结构,在 goroutine 之间进行同步和通信。
- 通道可以用于在两个或多个 goroutine 之间传递特定类型的值。
- 使用 make 函数创建通道,可以指定通道的容量(缓冲通道)或不指定容量(无缓冲通道)。
- 通道的发送操作使用
<-操作符,接收操作也使用<-操作符。
- 通道的发送和接收操作会阻塞,直到另一端准备好。这种机制可以实现 goroutine 之间的同步和数据传递。
package main
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)
}
}
func main() {
CalSquare()
}
sync
- 可以使用 sync.Mutex创建锁
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) // <=1000
x = 0
for i := 0; i < 5; i++ {
go addWithLock()
}
time.Sleep(time.Second)
println("WithLock:", x) //==1000
}
func main() {
Add()
}
- 协程间同步(sync.WaitGroup)
package main
import "sync"
func hello(i int) {
println("hello goroutine : ", i)
}
func ManyGoWait() {
var wg sync.WaitGroup
wg.Add(5) // 计数器加5
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done() // 计数器减1
hello(j)
}(i)
}
wg.Wait() // 阻塞直到计数器为0
}
func main() {
ManyGoWait()
}
02. 依赖管理
go依赖管理经历了三个阶段GOPATH -> Go Vendor -> Go Module,现在主流使用Go Module
-
GOPATH
-
GOPATH 是 Go 语言支持的一个环境变量,它指定了 Go 项目的工作区目录。
-
GOPATH 目录下包含三个主要文件夹:bin、pkg 和 src。
文件夹 作用 bin 项目编译的二进制文件 pkg 项目编译的中间产物 src 项目源码 -
在 GOPATH 中,项目的代码直接依赖于 src 目录下的代码。
-
使用
go get命令可以方便地下载并安装最新版本的包到 src 目录下。
-
-
Go Vendor
- Go Vendor 是在 GOPATH 基础上引入的一种依赖管理方式。
- 在项目目录下增加了 vendor 文件夹,所有依赖包以副本的形式存放在项目的 vendor 目录下。
- 当项目存在 vendor 目录时,Go 会优先使用 vendor 目录下的依赖包,如果依赖包不存在,则会从 GOPATH 中寻找。
- 使用 Go Vendor 可以解决多个项目需要同一个包依赖的冲突问题,每个项目引入一份依赖的副本。
-
Go Module
Go Module 是 Go 语言官方推出的依赖管理解决方案,它包含了三个重要的要素:配置文件、中心仓库和本地工具。
要素 工具 配置文件,描述依赖 go.mod 中心仓库管理依赖库 Proxy 本地工具 go get/go mod-
go get 使用
go get example.org/pkg +...后面跟不同的指令能实现不同的功能:
指令 功能 @update 默认 @none 删除依赖 @v1.1.2 下载指定tag版本,语义版本 @23dfdd5 下载特定的commit版本 @master 下载分支的最新commit -
go mod 使用
指令 功能 init 初始化,创建go.mod文件 download 下载模块到本地缓存 tidy 增加需要的依赖,删除不需要的依赖
-