当 Go 的 channel 被 close 后读写操作会怎么样?

当 Go 的 channel 被 close 后,对它的读操作行为有以下明确规则:


重点行为总结

操作 行为
从已关闭且仍有缓存数据的 channel 读 会正常返回该数据
从已关闭且缓冲区数据已读完的 channel 读 返回 零值 (基于类型)和 ok=false
向已关闭的 channel 写数据 ❌ 直接 panic

如果 channel 没有缓冲 和有缓冲的读完数据后的操作是一样的结果


示例代码

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

v, ok := <-ch // v=1, ok=true
v, ok = <-ch // v=2, ok=true
v, ok = <-ch // v=0, ok=false

range 遍历已关闭 channel

当你使用 range 遍历 channel 时,它会一直读到 channel 关闭且数据读完后才退出循环:

go 复制代码
for v := range ch {
    fmt.Println(v)
}
fmt.Println("done")

零值返回示例

如果 channel 是 chan string,零值读出来就是 ""

如果是 chan *User,零值就是 nil


为什么要设计成这样?

  • 避免读端阻塞
  • 让接收端可以用 ok 判断数据是否结束
  • 使 channel 更像是一个有限流(stream)

典型使用场景

生产者关闭 channel 通知消费者不再有新数据

go 复制代码
func producer(out chan<- int) {
    defer close(out)
    for i := 0; i < 5; i++ {
        out <- i
    }
}

func consumer(in <-chan int) {
    for v := range in {
        fmt.Println(v)
    }
}

常见误区

误区 实际情况
close 后读会 panic ❌ 永远不会 panic
必须由接收方 close ❌ 通常是发送方 close
close 可重复调用 ❌ 重复 close 会 panic

完整示例代码

go 复制代码
package main

import (
    "fmt"
)

func main() {
    ch := make(chan int, 3)

    // Producer
    go func() {
        for i := 0; i < 5; i++ {
            ch <- i
        }
        close(ch) // 通知消费者:不再有新数据
    }()

    // Consumer
    for v := range ch { // 会一直读到 ch 被关闭 & 数据读完
        fmt.Println("received:", v)
    }

    fmt.Println("done") // 会执行,因为 range 自动退出
}

输出示例(顺序可能不同)

sh 复制代码
received: 0
received: 1
received: 2
received: 3
received: 4
done
相关推荐
wuk9981 分钟前
C# 开发 FTP 客户端
开发语言·c#
淼淼7638 分钟前
Qt拖动工具栏控件到图页中均匀展示
开发语言·c++·windows·qt
二狗哈13 分钟前
Cesium快速入门22:fabric自定义着色器
运维·开发语言·前端·webgl·fabric·cesium·着色器
白狐_79814 分钟前
计算机网络复习全书(详细整理)
开发语言·计算机网络·php
黑岚樱梦14 分钟前
Linux系统编程
java·开发语言·前端
Kristen_YXQDN16 分钟前
PyCharm 中 pytest 运行 python 测试文件报错:D:\Python_file\.venv\Scripts\python.exe: No module named pytest
运维·开发语言·python·pycharm·pytest
IMPYLH18 分钟前
Lua 的 Debug(调试) 模块
开发语言·笔记·python·单元测试·lua·fastapi
咕白m62526 分钟前
使用 C# 设置 Word 段落对齐样式
后端·c#
九死九歌27 分钟前
【Sympydantic】使用sympydantic,利用pydantic告别numpy与pytorch编程中,tensor形状带来的烦人痛点!
开发语言·pytorch·python·机器学习·numpy·pydantic
Kiri霧28 分钟前
Go切片详解
开发语言·后端·golang