Golang语言中通道(channel)的使用总结

Posted by Shi Hai's Blog on August 10, 2025

个人学习使用,此博客由Copilot生成。

Go 语言 Channel 的 <-ch 用法与同步场景总结

在 Go 语言中,<- 是 Channel(通道)操作符,通常用于数据的发送和接收。本文总结了 <-ch 的典型用法、常见问题和实际同步场景,适合归档查阅。


1. <-ch 的基本含义

  • <-ch 表示“从 channel ch 接收一个值”。
  • 常见用法:
    • x := <-ch:从 channel 接收值并赋值给 x
    • <-ch:从 channel 接收值但不使用,常用于同步或等待信号。

2. 典型用法举例

ch := make(chan int)
go func() {
    ch <- 10 // 向通道发送 10
}()

x := <-ch // 接收值并赋给 x,x == 10
<-ch      // 仅接收值但不处理,常用于同步

3. 会不会出现空指针(nil)情况?

ch 为 nil 的情况

var ch chan int // 没有 make,ch 是 nil
<-ch            // 会发生什么?
  • 结果:会导致当前 goroutine 永久阻塞(deadlock),不会 panic,也不会出现“空指针异常”,但会让程序卡住。

已 make 但无数据

ch := make(chan int)
<-ch // 阻塞,直到有数据可读
  • 结果:阻塞,不会 panic。

已关闭的 channel

ch := make(chan int, 1)
ch <- 10
close(ch)
v, ok := <-ch // v=10, ok=true
v, ok := <-ch // v=0, ok=false,通道已关闭且无数据
  • 结果:不会 panic,读到零值和 false。

小结

  • nil channel: <-ch 永久阻塞,不 panic。
  • 已初始化 channel 无数据:阻塞,不 panic。
  • 关闭的 channel:返回零值,不 panic。
  • Go 没有传统“空指针异常”,但 nil channel 阻塞是常见 bug。

4. <-ch 用于同步/阻塞的典型场景

<-ch 仅用于同步或阻塞,值被丢弃。典型场景是等待某个 goroutine 完成,只关心信号,不关心内容。

示例一:单个 goroutine 完成信号

func main() {
    done := make(chan struct{})
    go func() {
        // ...做一些工作
        done <- struct{}{} // 发送信号
    }()
    <-done // 阻塞等待信号,值丢弃
    println("main received done signal")
}
  • chan struct{}:零内存,适合只做信号同步。
  • <-done 用于阻塞主流程,直到 goroutine 完成。

示例二:等待多个 goroutine 完成

func main() {
    done := make(chan struct{})
    for i := 0; i < 3; i++ {
        go func(i int) {
            // ...做一些工作
            done <- struct{}{}
        }(i)
    }
    // 等待全部 goroutine 完成
    for i := 0; i < 3; i++ {
        <-done // 阻塞多次,丢弃信号
    }
    println("all goroutines done")
}
  • 多个 goroutine 都往同一个 channel 发送信号,主流程用 <-done 多次等待全部完成。

5. 实践建议

  • 只需等待信号、无需数据时,推荐用 chan struct{},配合 <-ch
  • 并发较复杂时建议用 sync.WaitGroup,其本质也是信号同步,但更易用。
  • 若 channel 可能为 nil,建议提前判断:
if ch != nil {
    <-ch
}

6. 总结

  • <-ch 是 Go 并发同步的基础手段,无论是收数据还是仅同步。
  • nil channel 导致阻塞是常见陷阱,需注意初始化。
  • <-ch 丢弃值的用法,常见于 goroutine 同步、信号通知等场景。

参考资料: