golang channel通道入门与实例

文章发布于 2023-08-30

Go语言中的通道channel是一种用于在不同协程之间传递数据的数据结构。通道提供了一种同步机制,用于确保协程之间的通信安全和数据同步。下面是关于Go通道的详细解释以及一个使用实例:

通道的基本概念

通道的声明: 通道可以通过使用 make 函数来声明和初始化。

ch := make(chan int) // 创建一个用于传递 int 类型数据的通道

通道的发送和接收: 使用 <- 操作符来发送和接收数据。

ch <- data // 发送数据到通道
receivedData := <-ch // 从通道接收数据

通道的关闭: 通道可以被关闭,以便通知接收方不会再有更多的数据。

close(ch)	

通道的使用

以下是一个使用通道来计算并发任务的示例。我们将使用两个协程来计算一系列数字的平方,并将结果发送到一个通道中,然后从通道中接收这些结果。

package main

import (
    "fmt"
    "sync"
)

func squareWorker(id int, numbers []int, resultChan chan<- int, wg *sync.WaitGroup) {
    defer wg.Done() // 告知 WaitGroup 任务完成

    for _, num := range numbers {
        result := num * num
        fmt.Printf("Worker %d: %d * %d = %d\n", id, num, num, result)
        resultChan <- result // 发送结果到通道
    }
}

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    numWorkers := 2

    resultChan := make(chan int) // 创建通道用于存放结果
    var wg sync.WaitGroup

    for i := 0; i < numWorkers; i++ {
        wg.Add(1) // 增加 WaitGroup 的计数
        go squareWorker(i, numbers, resultChan, &wg)
    }

    go func() {
        wg.Wait()     // 等待所有任务完成
        close(resultChan) // 关闭通道,表示数据发送完毕
    }()

    // 从通道中接收结果并打印
    for result := range resultChan {
        fmt.Println("Received result:", result)
    }
}

打印结果:并发执行的,所以每次打印出来的顺序可能都会不一样

Worker 0: 1 * 1 = 1
Worker 0: 2 * 2 = 4
Worker 1: 1 * 1 = 1
Received result: 1
Received result: 4
Received result: 1
Worker 0: 3 * 3 = 9
Worker 0: 4 * 4 = 16
Worker 1: 2 * 2 = 4
Received result: 9
Received result: 16
Received result: 4
Worker 0: 5 * 5 = 25
Received result: 25
Worker 1: 3 * 3 = 9
Worker 1: 4 * 4 = 16
Received result: 9
Received result: 16
Worker 1: 5 * 5 = 25
Received result: 25

在这个例子中,我们定义了一个 squareWorker 函数来计算数字的平方并将结果发送到通道中。main 函数创建了一个通道 resultChan 用于接收结果,以及一个 sync.WaitGroup 用于等待所有协程完成。我们创建了两个协程来执行 squareWorker 函数,并在主协程中等待它们完成。在一个单独的协程中,我们使用匿名函数来等待所有任务完成并关闭通道。

通过这种方式,我们实现了并发计算和结果的通信,确保了协程之间的同步。