为什么go 的channel需要关闭?

golang中的channel有关闭的操作。
我觉得挺奇怪,为什么需要关闭通道,如果不需要,不再往里放数据不就行了?然后让GC回收掉这个通道不是没了?何必多此一举,反正close的时候你肯定是不会再用这个通道了。

阅读 5.7k
4 个回答

close 是告诉接受者里面不会再有任何数据了。

从一个 channel 读取数据,但里面没有数据,读取会阻塞。但是如果 channel 已经关闭了,就会立即返回一个零值,同时可以通过多返回值的语法检测 channel 是否已经关闭了。

关闭 channel 这个动作本身,也是给接受者的一个信号。

合适的时机 close() 可以避免一些死锁的情况。推荐一本书,《Go 语言并发之道》里面对 channel 的使用有很符合实战的介绍。

结论: 如果使用 range 遍历 channel 如果不 close 将会阻塞

我们使用 channel 一般有 2 种方式. 方式1 是 for + select, 方式2 是 for range

方式1

for {
    select {
    case <-ch:
        // do something
    }
}

方式2

如果我们只需要遍历有限次数的 channel, 可以采用 range 的方式遍历

for v := range ch {
    // do something
}

我们使用方式2的时候, 如果我们需要运行完一定的次数就退出, 我们就需要 close

方式2, 不 close

ch := make(chan int, 3)
for i := 0; i < 3; i++ {
    ch <- i
}

// 这里不 close, 将会一直阻塞
for v := range ch {
    fmt.Println(v)
}

fmt.Println("end")

输出

0
1
2

这里不 close, 将会一直阻塞, 无法输出 end

方式2, close

ch := make(chan int, 3)
for i := 0; i < 3; i++ {
    ch <- i
}

close(ch)

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

fmt.Println("end")

输出

0
1
2
end

这里 close, 将会正常输出 end

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题