一.语言进阶
1.1Goroutine
- 定义了一个名为
hello(i int)的函数,该函数接受一个整数参数i,并打印出“hello goroutine : ” +i的值。 - 定义了一个名为
HelloGoRoutine()的主函数,在这个函数内部有一个for循环,从0遍历到4,每次迭代都会启动一个新的goroutine来调用hello(j)函数,其中j是从循环得到的当前索引值。
1.2CSP
Channels
Channels 是 Go 语言中用于 goroutines 之间通信的机制。Channels 是类型化的,这意味着它们只能传输特定类型的数据。创建 channel 的语法如下:
chan T // T 是 channel 传输的数据类型
可以使用 make 函数来初始化一个 channel:
ch := make(chan int) // 创建一个传输 int 类型的 channel
Channels 有两种操作:发送(<-)和接收(<-)。
- 发送:
ch <- value将值发送到 channel。 - 接收:
value := <-ch从 channel 接收值。
CSP 在 Go 中的实现
以下是 CSP 在 Go 语言中的实现方式:
- 创建 Goroutines:通过
go关键字启动多个并发执行的函数。 - 使用 Channels 进行通信:这些 goroutines 通过 channels 发送和接收数据来进行通信。
- 同步和消息传递:goroutines 通常通过 channels 进行同步,而不是通过共享内存。这是 CSP 的核心原则之一。
下面的例子展示了如何在 Go 中使用 CSP:
package main
import "fmt"
func main() {
// 创建一个 channel
message := make(chan string)
// 启动一个新的 goroutine
go func() {
// 向 channel 发送数据
message <- "Hello, CSP in Go!"
}()
// 从 channel 接收数据
msg := <-message
fmt.Println(msg)
}
在这个例子中,一个 goroutine 发送了一条消息到 message channel,而主 goroutine 从这个 channel 接收了这条消息并打印出来。这种通信方式确保了数据的安全交换,并遵循了 CSP 的原则。
1.3并发安全Lock
- 定义变量和锁:
- 定义了一个整型变量
x和一个互斥锁lock sync.Mutex。
- 定义了一个整型变量
- 带锁的加法函数 (
addWithLock) :- 使用互斥锁保证并发安全。
- 在循环中对变量
x执行2000次加一操作,每次操作前锁定互斥锁,操作完成后解锁。
- 不带锁的加法函数 (
addWithoutLock) :- 不使用任何锁,直接执行2000次加一操作。
- 测试程序 (
TestAddLock) :- 程序创建了5个协程,分别执行带锁和不带锁的加法函数。
- 测试结果显示,使用锁的情况下,最终结果正确(10000);而不使用锁的情况下,由于竞态条件,结果错误(8382)。
二.依赖管理
1. GOPATH (早期)
在Go的早期版本中,依赖管理主要通过GOPATH环境变量实现。用户需要将所有的项目放在GOPATH指定的目录下,Go工具会在这个目录下查找依赖的包。
缺点:
- 无法指定依赖的版本,只能使用最新的代码。
- 不同项目之间的依赖可能会发生冲突。
2. Go Vendor (Go 1.5引入)
为了解决GOPATH的问题,Go 1.5引入了vendor目录。每个项目可以有一个vendor目录,其中包含了项目所有的依赖。这样,每个项目可以使用自己的依赖版本,而不会受到GOPATH中其他项目的影响。
缺点:
- 仍然没有很好的版本控制机制。
- 管理依赖版本和更新依赖比较繁琐。
3. Go Modules (Go 1.11引入)
Go Modules是Go语言官方推荐的依赖管理工具,它提供了一种声明式的依赖管理方式,并且支持版本控制。 主要特点:
- 使用
go.mod文件来记录项目的依赖和版本。 - 可以通过
go get命令添加、更新或删除依赖。 - 支持语义版本控制(Semantic Versioning),可以指定依赖的版本号。
- 可以使用
replace指令在go.mod文件中替换依赖的版本或位置。 - 支持模块代理(如
GOPROXY),可以加速模块的下载。 使用Go Modules的基本步骤如下: - 初始化模块:在项目目录下运行
go mod init <module-name>,这会创建一个go.mod文件。 - 添加依赖:编写代码时,Go工具会自动解析并添加所需的依赖到
go.mod文件中。 - 更新依赖:可以使用
go get来更新依赖到特定的版本或最新的版本。 - 清理依赖:运行
go mod tidy可以清理掉未使用的依赖。 Go Modules的引入极大地改善了Go语言的依赖管理,使得依赖管理更加方便、可靠和高效。从Go 1.13版本开始,Go Modules成为Go语言依赖管理的默认方式。