我是Golang的新手并且遇到了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
ch 频道的 len 和上限似乎很奇怪但代码仍然有效。但是当我运行这段代码时:
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)
}
结果变为: len: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
那么,任何人都可以告诉我以下问题:
为什么 make(chan int)会返回一个零 len和零上限的频道,但仍可在第一段代码中正常使用片
为什么第二个代码使用主函数中的而不是新的goroutine 导致死锁?
为什么我在第三段代码中为 make 添加上限参数可以解决问题?
渠道(第一和第二代码)与零渠道有什么区别?
谢谢!
答案 0 :(得分:2)
您可以创建两种类型的频道:缓冲频道和无缓冲频道
缓冲通道是具有容量的通道:make(chan int, 10)
缓冲通道允许您向其发送与其容量相同数量的消息,而不会被阻止
无缓冲的频道没有容量,这就是为什么你的发送goroutine将被阻止,直到另一个goroutine从它接收。
1。这是无缓冲的频道。你从主频道接收主要goroutine被阻止,直到新的goroutine向它发送消息。
2。因为您使用的是无缓冲通道,所以发送goroutine会被阻止,直到另一个接收它,但除了主要通道外,您没有其他goroutine,因此程序处于死锁状态。
3。由于缓冲的goroutine。它的容量为1,因此向它发送一条消息然后在同一个goroutine中接收它就不会有问题。但是,如果您尝试向其发送多条消息,则会被阻止。 ch <- 233; ch <- 233
- 此代码将导致死锁。
4。得到了你的意思......但是如果你试图接收或发送到nil频道,你将被屏蔽:var ch chan int; <-ch
或var ch chan int; ch <- 1
< / p>