这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
一、本堂课重点内容
并发
- Goroutine
- csp (通过通信共享内存)
- channel
- lock
- wait group
依赖管理
- go mod
- go workspace
二、详细知识点介绍:
并发
channel
-
go 的 channel 默认是双向的,既可以 send,也可以 recv
-
channel 必须有发送端和接收端,否则就 panic
-
make(chan int, n) n 表示缓冲区大小,可以省略,默认为 0
- 而对于无缓冲 channel,接受和发送都要在不同携程之间,不让两个人互相阻塞
- 对于有缓冲区 channel,在缓冲区大小内,两个不会互相阻塞,可以在同一协程内
- 如果超过缓冲区大小,就会 panic,所以超过缓冲区大小的还是必须在其他的协程中处理
-
缓冲区也有 len 和 cap 的概念
-
对于 rust,如果超出缓冲区大小 send 就会返回 Error
func sendData(sendch chan<- int) {
sendch <- 10
}
func main() {
cha1 := make(chan int)
go sendData(cha1)
fmt.Println(<-cha1)
}
单向 channel
// 声明参数是一个只能发送的 ch
func sendData(sendch chan<- int) {
sendch <- 10
}
func main() {
// 声明一个只能发送的 channel,下面使用它去接受就会 panic
// 如果声明为 chan int,下面的接受不会 panic,在 sendData 会被转换为只能发送的 channel,而 main 中的仍然是双向的
sendch := make(chan<- int)
go sendData(sendch)
fmt.Println(<-sendch)
}
关闭 channel
不能一直 send 或者一直 recv,处理完及时把一端 close 了
func producer(chnl chan int) {
for i := 0; i < 10; i++ {
chnl <- i
}
// 发送完成后,使用 send 函数显式关闭 channel
close(chnl)
}
func main() {
ch := make(chan int)
go producer(ch)
for {
// 通过 ok 判断 channel 是否关闭
v, ok := <-ch
if ok == false {
break
}
fmt.Println("Received ", v, ok)
}
}
Go mod
go 1.11 加入, go 1.16 成为默认
go proxy
-
无法保证构建的稳定性
- 代码库作者可以在 github 等平台随意增加删除修改软件库
-
无法保证依赖的可用性
- 依赖可能被删除
-
增加第三方平台压力
Go Proxy 可以缓存来自各个源的软件, 保证了稳定性, 我们会从 Proxy 拉代码
和常用的缓存有类似之处, 如果一层 proxy 不能解决, 那就来两层 🐶
go get
go get example.org/pkg
在后面可以添加其他东西
- @update 默认, 拉最新的
- @none 删除依赖
- @v1.1.2 tag 版本, 语义版本
- @23dfdd 特定的 commit
- @master 特定的分支
go tidy
初始化, 创建 go.mod 文件
go mod init xxx
go download
下载模块到本地缓存
go mod download
go tidy
增加需要的依赖, 删除不需要的依赖
go mod tidy
依赖关系
假如有以下依赖关系
main --> A --> C 1.4 --> D
\ /
-> B --> C 1.3 -
C 1.2
C 1.1
那么最后编译时
- A 会用 C 1.4 编译?
- B 会用 C 1.3 编译?
都不是, 最后都会用 C 1.4 编译, Go 语言会使用算法选择一个最低的兼容版本, 这里 1.3 和 1.4 兼容, 就会选择 1.4
Go Work
基本使用
通过 go work init 创建一个 go.work 文件
go 1.18
use (
./path-to-upstream-mod-dir
./path-to-your-module
)
go.work文件的语法与go.mod文件相似,包含以下指令。
- go:go工具链的版本,例如:go 1.18
- use:将一个模块添加到工作区的集合中
- 它的参数是包含该模块 go.mod 文件的目录的相对路径。
- use 指令不会在指定目录的子目录中添加模块。
- replace: 与go.mod文件中的替换指令类似
- go.work 文件中的替换指令用其他地方的内容替换一个模块的特定版本或所有版本。
更多
除了 go work init 和 go work use ,Go 1.18为工作区引入了以下命令。
go work sync:将 go.work 文件中的依赖关系推回到每个工作空间模块的go.mod文件中。
go work edit:为编辑 go.work 提供一个命令行界面,主要由工具或脚本使用。
三、实践练习例子:
四、课后个人总结:
go work 老师没讲到, 不过看资料时看到了, 感觉非常不错, 项目中一定用起来
五、引用参考:
- Lock pkg.go.dev/sync
- Go Mod go.dev/blog/using-…