Go语言第二讲 | 青训营笔记

52 阅读3分钟

Goroutine、Communicating Sequential Processes (CSP)、Channel和WaitGroup是Go语言中强大的并发编程工具。它们提供了一种简单而有效的方式来处理并发任务,并实现不同协程(goroutine)之间的通信和同步。本文将介绍这些概念,并附带简单的测试代码,以帮助读者更好地理解它们的用法和优势。

Goroutine是Go语言中轻量级线程的概念,它可以在程序中并发执行。与传统的线程相比,Goroutine的启动和销毁开销较小,因此可以轻松创建大量的协程。可以使用关键字"go"来启动一个Goroutine,例如:

goCopy codego func() {
    // 协程执行的代码
}()

CSP是一种并发编程模型,由Tony Hoare于1978年提出。它基于通信顺序进程的概念,强调通过通信来共享数据而不是通过共享数据来通信。在Go语言中,CSP的核心概念是Channel。

Channel是用于协程之间通信的管道。它可以在不同的协程之间发送和接收数据。通过Channel,协程可以安全地传递数据,避免了数据竞争的问题。可以使用内置的make函数创建一个Channel,例如:

goCopy code
ch := make(chan int)

Channel提供了发送和接收操作符,分别是"<-"和"->"。例如,将数据发送到Channel中:

goCopy code
ch <- data

从Channel中接收数据:

goCopy code
data := <-ch

WaitGroup用于等待一组协程完成执行。它可以用来同步主协程和其他协程的执行。可以使用WaitGroup的三个方法:Add()、Done()和Wait()。例如,假设有3个协程需要等待:

goCopy codevar wg sync.WaitGroup
​
for i := 0; i < 3; i++ {
    wg.Add(1)
​
    go func() {
        // 协程执行的代码
​
        wg.Done()
    }()
}
​
wg.Wait()

下面是一个简单的示例,演示了如何使用Goroutine、CSP和WaitGroup来实现并发任务的协调和通信。假设我们需要计算一系列数字的平方,并将结果发送到一个Channel中:

goCopy codepackage main
​
import (
    "fmt"
    "sync"
)
​
func main() {
    var wg sync.WaitGroup
    numbers := []int{1, 2, 3, 4, 5}
    results := make(chan int)
​
    for _, num := range numbers {
        wg.Add(1)
​
        go func(n int) {
            square := n * n
            results <- square
​
            wg.Done()
        }(num)
    }
​
    go func() {
        wg.Wait()
        close(results)
    }()
​
    for res := range results {
        fmt.Println(res)
    }
}

在上面的代码中,

我们首先定义了一个WaitGroup变量wg用于等待协程的完成。然后,我们创建了一个整数切片numbers,以及一个用于存储结果的results通道。

接下来,我们使用range迭代numbers切片,为每个数字启动一个协程。在每个协程中,我们计算数字的平方,并将结果发送到results通道中。在协程完成后,我们使用wg.Done()表示协程的结束。

在主函数中,我们还启动了一个额外的协程。它会等待所有的协程完成后关闭results通道。这样做是为了确保在主函数中的for res := range results循环能够正常结束。

最后,在主函数中,我们通过range results循环从results通道中接收结果,并打印出来。当results通道被关闭时,循环会自动结束。