Go 并发编程基础:通道(Channel)的使用

在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。

本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。


一、Channel 简介

Channel 是 Go 语言中实现 "通信顺序进程"(CSP)模型的关键组件。

  • • 用于在多个 Goroutine 之间传递数据
  • • 本质上是一个 先进先出 的队列
  • • 保证并发安全

通道类型的声明格式:

go 复制代码
var ch chan 数据类型

二、Channel 的创建与基本使用

go 复制代码
ch := make(chan int) // 创建一个传输 int 类型的无缓冲通道

发送与接收数据:

go 复制代码
ch <- 10     // 发送数据
x := <- ch   // 接收数据

注意:无缓冲通道发送和接收都是阻塞的,直到对方准备好。

示例:

go 复制代码
func worker(ch chan string) {
    msg := <-ch
    fmt.Println("接收到:", msg)
}

func main() {
    ch := make(chan string)
    go worker(ch)
    ch <- "Hello, Channel"
}

三、带缓冲的 Channel

go 复制代码
ch := make(chan int, 3) // 创建一个缓冲区大小为3的通道

特点:

  • • 发送操作在缓冲区满时阻塞
  • • 接收操作在缓冲区空时阻塞
r 复制代码
ch <- 1
ch <- 2
fmt.Println(<-ch) // 输出 1

四、通道的关闭

scss 复制代码
close(ch)
  • • 关闭通道后不能再发送数据,但仍可接收剩余数据
  • • 读取已关闭通道不会阻塞,返回类型零值
  • • 可以用 v, ok := <-ch 判断通道是否关闭

示例:

go 复制代码
ch := make(chan int, 2)
ch <- 10
ch <- 20
close(ch)

for v := range ch {
    fmt.Println(v)
}

五、单向通道

可以将通道限制为只发送 或只接收:

go 复制代码
func send(ch chan<- int) {
    ch <- 100
}

func recv(ch <-chan int) {
    fmt.Println(<-ch)
}

六、使用 select 同时监听多个 Channel

go 复制代码
select {
case msg1 := <-ch1:
    fmt.Println("ch1:", msg1)
case msg2 := <-ch2:
    fmt.Println("ch2:", msg2)
default:
    fmt.Println("无数据可读")
}

特点:

  • • select 会等待多个通道中的一个准备好
  • • 如果多个都准备好了,则随机选择一个执行
  • • 使用 default 实现非阻塞操作

七、超时控制

结合 time.After() 实现超时机制:

css 复制代码
select {
case data := <-ch:
    fmt.Println("收到数据:", data)
case <-time.After(2 * time.Second):
    fmt.Println("超时未收到数据")
}

八、通道的常见应用场景

场景 描述
Goroutine 通信 不共享内存,通过通道交换数据
控制并发数量(限流) 使用带缓冲通道实现并发任务限制
Worker Pool(协程池) 多个 worker 从任务通道中取任务处理
信号通知/任务完成通知 通道发送空 struct{} 信号实现同步或退出控制
超时控制 / 取消上下文 select + time.After / context 控制并发

九、小结

  • • Channel 是 Go 并发通信的核心工具
  • • 区分无缓冲/有缓冲通道,理解其阻塞机制
  • • 使用 close 安全关闭通道
  • • select 可实现多路复用、超时控制等高级场景

相关推荐
大鸡腿同学2 小时前
手心向上,手心向下
后端
CCblandy3 小时前
令牌桶在 0.9 倍负载超发 19%、固定窗口边界放行 20 个:四种限流算法同构实测
后端·python·算法·性能优化·架构
凤山老林5 小时前
Spring Boot 集成 Sa-Token 实现高可用权限认证:登录鉴权、动态路由权限与接口防重放实战
spring boot·后端·sa-token·bootstrap
Bazingga6 小时前
一次推理的完整旅程:ReAct推理深度解析
后端
姜鱼问生6 小时前
Nginx gzip 压缩:一个配置让页面加载快 3 倍
后端·算法·架构
颜酱6 小时前
一栋商业大厦,讲清 InnoDB 的表空间、段、区和页
后端·mysql
码事漫谈6 小时前
1956 亿行数据该怎么存:金仓时序数据库的三个实测
后端
Wx-bishekaifayuan6 小时前
springboot桂味美食分享系统40540-计算机课程设计、毕业设计
spring boot·后端·python·django·课程设计·express·旅游
彭亚川Allen6 小时前
从零手搓 RAG 之检索全流程,给大模型接上自己的知识库
前端·后端·ai编程
IT_陈寒7 小时前
别让Java字符串拼接偷偷吃掉你的内存
前端·人工智能·后端