解锁Go语言中的4 —— 探索Go语言中的并发与并行
- 资料
- 2026-07-05 03:17:35
- 4
在编程的世界里,数字“4”不仅仅是一个简单的数字,它还承载着特殊的含义和力量,在Go语言中,“4”更是并发与并行编程的代名词,让我们用费曼的方法,以一种简单易懂的方式,一起探索Go语言中那些与“4”紧密相连的神奇之处。
什么是Go语言的并发与并行?
什么是并发?
并发(Concurrency)指的是程序在执行过程中,同时处理多个任务的能力,在Go语言中,它通过goroutine实现,goroutine是Go语言特有的轻量级线程,可以非常高效地处理高并发任务,想象一下,你同时听音乐、浏览网页、打字和思考,这就是并发在生活中的体现。
什么是并行?
并行(Parallelism)则是指多个任务在同一时间点上真正地同时执行,虽然现代计算机的CPU通常只有几个核心,但通过操作系统的调度和Go语言的goroutine,我们可以让多个任务“看起来”像是同时进行,这就像你一边听音乐一边打电话,两件事几乎同时进行,但实际上是你在一个时间点上切换了注意力。
Go语言中的“4个G”
Go语言之所以在并发与并行编程上如此强大,离不开其背后的“4个G”:Goroutines、Channels、Select和Group Wait,这四个概念共同构成了Go语言并发编程的基石。
Goroutines(G)
Goroutines是Go语言的核心特性之一,它允许你以非常轻量级的方式运行多个任务,启动一个新的goroutine就像调用一个函数那样简单:go func() { /* 代码 */ }(),Goroutines由Go的运行时管理,它们共享内存但通过channel进行通信。
示例代码:
go func() {
fmt.Println("Hello from goroutine 1")
}()这段代码创建了一个新的goroutine并立即执行其中的代码。
Channels(C)
Channels是Goroutines之间通信的桥梁,你可以把它想象成两个goroutine之间的信使,负责传递消息,Channels可以防止数据在并发环境中被错误地访问或修改,是Go语言中实现安全通信的关键。
示例代码:
ch := make(chan string) // 创建一个字符串类型的channel
go func() {
ch <- "Hello, World!" // 发送消息到channel
}()
fmt.Println(<-ch) // 从channel接收消息并打印这段代码创建了一个channel并启动了一个goroutine来发送消息,然后从channel接收并打印消息。
Select(E)
Select语句允许你同时监听多个channel上的操作(如发送、接收),并根据哪个channel准备就绪来执行相应的操作,这就像是一个多路复用器,可以让你高效地管理多个通信通道。
示例代码:
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(1 * time.Second) // 模拟延时操作
ch1 <- "First"
}()
go func() {
time.Sleep(2 * time.Second) // 模拟更长的延时操作
ch2 <- "Second"
}()
select {
case msg1 := <-ch1: // 如果ch1有数据可读,则执行此case
fmt.Println("Received", msg1) // 打印ch1的消息并退出select块
case msg2 := <-ch2: // 如果ch2有数据可读,则执行此case(实际上不会执行)
fmt.Println("Received", msg2) // 但这里不会打印ch2的消息,因为ch1先就绪了
}这段代码展示了select如何根据channel的准备情况来选择执行哪个case。
4. Group Wait(WaitGroup)
WaitGroup(G)用于等待一组goroutines的执行完成,它非常适合于当你需要确保所有子任务都完成后才继续执行主任务的场景,通过sync.WaitGroup的Add、Done和Wait方法,你可以轻松地管理goroutine的同步问题。
示例代码:
var wg sync.WaitGroup // 创建一个WaitGroup实例
wg.Add(2) // 增加等待计数为2,表示有2个goroutine需要等待完成
go func() { // 启动第一个goroutine...}() // 省略具体实现... wg.Done() // 完成一个任务后调用Done()表示该goroutine已完成 wg.Wait() // 主任务等待所有goroutine完成...} // 省略具体实现... } // 主函数结束时调用wg.Done()表示主任务也完成了(虽然这里不必要) ```
发表评论