Go语言中与工作协程的通道通信

GolangGolangBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在 Go 语言中,关闭一个通道(channel)可用于向通道的接收者传达完成信息。本实验将演示如何使用通道将 main() 协程中待完成的工作传达给一个工作协程,以及当工作协程没有更多任务时如何关闭通道。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("`Golang`")) -.-> go/ConcurrencyGroup(["`Concurrency`"]) go/ConcurrencyGroup -.-> go/channels("`Channels`") subgraph Lab Skills go/channels -.-> lab-15460{{"`Go语言中与工作协程的通道通信`"}} end

关闭通道

在本实验中,你需要修改给定的代码,以便在工作协程没有更多任务时关闭 jobs 通道。你还需要使用 done 通道来通知所有任务已完成。

  • 使用一个带缓冲的通道 jobs,将 main() 协程中待完成的工作传达给一个工作协程。
  • 使用通道 done 来通知所有任务已完成。
  • 使用一个工作协程,通过 j, more := <-jobsjobs 通道中反复接收数据。
  • 使用接收的特殊双值形式,在所有任务完成时通过 done 通道进行通知。
  • 通过 jobs 通道向工作协程发送 3 个任务,然后关闭该通道。
  • 使用 同步 方法等待工作协程完成。
$ go run closing-channels.go
发送任务 1
接收任务 1
发送任务 2
接收任务 2
发送任务 3
接收任务 3
发送所有任务
接收所有任务

## 关闭通道的概念自然地引出了我们的下一个
## 示例:对通道使用 `range`。

以下是完整代码:

// 关闭一个通道表示不会再向其上发送更多值。
// 这对于向通道的接收者传达完成信息很有用。

package main

import "fmt"

// 在这个示例中,我们将使用一个 `jobs` 通道
// 来将 `main()` 协程中待完成的工作传达给一个工作协程。
// 当我们没有更多任务给工作协程时,我们将 `关闭` `jobs` 通道。
func main() {
	jobs := make(chan int, 5)
	done := make(chan bool)

	// 这是工作协程。它通过 `j, more := <-jobs` 从 `jobs` 通道中反复接收数据。
	// 在这种接收的特殊双值形式中,如果 `jobs` 已被 `关闭` 且通道中的所有值都已被接收,
	// 则 `more` 值将为 `false`。我们使用此来在完成所有任务时通过 `done` 通道进行通知。
	go func() {
		for {
			j, more := <-jobs
			if more {
				fmt.Println("接收任务", j)
			} else {
				fmt.Println("接收所有任务")
				done <- true
				return
			}
		}
	}()

	// 这通过 `jobs` 通道向工作协程发送 3 个任务,然后关闭该通道。
	for j := 1; j <= 3; j++ {
		jobs <- j
		fmt.Println("发送任务", j)
	}
	close(jobs)
	fmt.Println("发送所有任务")

	// 我们使用之前看到的 [同步](channel-synchronization) 方法等待工作协程完成。
	<-done
}

总结

在本实验中,你学习了如何使用通道将 main() 协程中待完成的工作传达给一个工作协程,以及当工作协程没有更多任务时如何关闭通道。你还学习了如何使用 done 通道来通知所有任务已完成。

您可能感兴趣的其他 Golang 教程