与 make 通道相关的奇怪死锁

Wierd deadlock related with make channel

我遇到了 Go 频道的奇怪行为。问题描述如下

package main

import "fmt"

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

    fmt.Println("len:", len(ch))
    fmt.Println("cap:", cap(ch))
    fmt.Println("is nil:", ch == nil)
                                                                         
    go func(ch chan int){
        ch <- 233
    }(ch)

    fmt.Println(<- ch)

}

当我运行上面的代码时,我得到这样的结果:

len: 0
cap: 0
is nil: false
233

通道 chlencap 看起来很奇怪,但代码仍然有效.但是当我 运行 这个代码时:

package main

import "fmt"

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

    fmt.Println("len:", len(ch))
    fmt.Println("cap:", cap(ch))
    fmt.Println("is nil:", ch == nil)
                                                                         
    ch <- 233 // Here changes!

    fmt.Println(<- ch)

}

结果变成了: 长度:0 上限:0 为零:假 致命错误:所有 goroutines 都睡着了 - 死锁!

goroutine 1 [chan send]:
main.main()
    /tmp/sandbox640280398/main.go:12 +0x340

更重要的是,当我像下面这样更改第二个代码片段时: 主包

import "fmt"

func main() {
    ch := make(chan int, 1) //Here changes!

    fmt.Println("len:", len(ch))
    fmt.Println("cap:", cap(ch))
    fmt.Println("is nil:", ch == nil)
                                                                         
    ch <- 233

    fmt.Println(<- ch)

}

事情又成功了,我得到了:

len: 0
cap: 1
is nil: false
233

所以,谁能告诉我以下问题:

  1. 为什么 make(chan int) return 具有 zero len 和 [=38 的频道=]零 上限,但在第一个代码段中仍然可以正常工作?

  2. 为什么第二个代码在主函数中使用通道而不是新的goroutine导致死锁?

  3. 为什么我在第三个代码的make中加一个cap参数可以解决问题?

  4. 通道(在第一个和第二个代码中)与 nil 通道有什么区别?

您可以创建两种类型的通道:缓冲通道和非缓冲通道。
缓冲通道是那些具有容量的通道:make(chan int, 10)
缓冲通道允许您向其中发送与其容量相同数量的消息而不会被阻塞。
无缓冲通道没有容量,这就是为什么您的发送 goroutine 将被阻塞,直到另一个 goroutine 收到它。

1. 是无缓冲通道。在新的 goroutine 向它发送消息之前,你的主 goroutine 在从通道接收时被阻塞。

2. 因为你使用的是无缓冲通道,你的发送 goroutine 被阻塞,直到另一个 goroutine 从它接收,但是除了主 goroutines 你没有其他 goroutines,所以程序在僵局。

3. 因为缓冲 goroutine。它的容量为 1,因此向它发送一条消息然后在同一个 goroutine 中接收它不会有问题。但是,如果您尝试向它发送超过 1 条消息,您将被阻止。 ch <- 233; ch <- 233 - 此代码将导致死锁。

4. 明白你的意思...,但如果你尝试接收或发送到一个 nil 频道,你将被阻止:var ch chan int; <-chvar ch chan int; ch <- 1