golang为什么不能在主线程上将值传递给通道
golang why can not pass value to channel on the main thread
案例1
package main
func main() {
dogChan := make(chan int)
dogChan <- 1
}
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/Users/xuzhongwei/Source/awesomeProject/main.go:5 +0x50
案例2
package main
func main() {
dogChan := make(chan int)
go func(ch chan int) {
}(dogChan)
dogChan <- 1
}
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/Users/xuzhongwei/Source/awesomeProject/main.go:9 +0x72
案例 3
package main
func main() {
dogChan := make(chan int)
go func(ch chan int) {
<- ch
}(dogChan)
dogChan <- 1
}
案例4
package main
func main() {
dogChan := make(chan int)
go func(ch chan int) {
<- ch
}(dogChan)
dogChan <- 1
dogChan <- 2
}
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/Users/xuzhongwei/Source/awesomeProject/main.go:10 +0x90
案例5
package main
func main() {
dogChan := make(chan int)
go func(ch chan int) {
for {
select {
case <- ch:
}
}
}(dogChan)
dogChan <- 1
dogChan <- 2
dogChan <- 3
dogChan <- 4
dogChan <- 5
}
谁能告诉我为什么 case1、case2 出错而 case3 正常?
在 case1 中,我的猜测是 dogChan 没有在 goroutine 中使用,所以它被视为关闭。
在 case2 中,我的猜测是虽然 dogChan 在 goroutine 中传递但它没有在 goroutine 中使用所以它被视为关闭
谁能告诉我为什么 case4 出错而 case5 正常?
为什么您认为 case1
和 case2
会发生这种情况?这些通道旨在充当发送方和接收方之间的同步原语。您有一个发件人在频道上发送,dogChan
但 none 正在接收。
没有接收 goroutine 或 goroutine 上的接收操作,发送方只是阻塞(作为一个无缓冲的通道)
同样的问题 case4
,你在通道上有两个发送,但在 goroutine 上有一个接收。 dogChan <- 2
将永远阻塞。在 case5
中,如果您的目的是从通道读取,只需使用 range
循环来迭代通过它发送的连续值。
Golang 期望程序读取放置在通道中的消息。
消费者 (reader) 需要从通道中排出(读取)所有消息,使用简单的 for-read 或 for-select。通道发送和接收都阻塞,直到发送方和接收方准备就绪。
- case1,case2 = 向通道发送一条消息,阻止等待 reader,读取零条消息
- case4 = 向通道发送一条消息,阻塞等待 reader,reader 不消耗(读取)消息
- case3 = 向通道发送一条消息,从通道消费一条消息,发送方块等待 reader
- case5 = 向通道发送五个消息,消耗所有(五个)消息,每个发送块直到 reader 收到
// for range over channel
for msg := range ch {
// process msg
}
// for select
done := false
for !done {
select {
case msg := <-ch: {
// process msg
}
case ch == nil: {
done = true
}
}
}
// producer should close channel
close(ch)
注:
- 通道可以缓冲,指定通道(队列)大小
- 通道大小默认 = 1(无缓冲),写入器在通道已满时阻塞
案例1
package main
func main() {
dogChan := make(chan int)
dogChan <- 1
}
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/Users/xuzhongwei/Source/awesomeProject/main.go:5 +0x50
案例2
package main
func main() {
dogChan := make(chan int)
go func(ch chan int) {
}(dogChan)
dogChan <- 1
}
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/Users/xuzhongwei/Source/awesomeProject/main.go:9 +0x72
案例 3
package main
func main() {
dogChan := make(chan int)
go func(ch chan int) {
<- ch
}(dogChan)
dogChan <- 1
}
案例4
package main
func main() {
dogChan := make(chan int)
go func(ch chan int) {
<- ch
}(dogChan)
dogChan <- 1
dogChan <- 2
}
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/Users/xuzhongwei/Source/awesomeProject/main.go:10 +0x90
案例5
package main
func main() {
dogChan := make(chan int)
go func(ch chan int) {
for {
select {
case <- ch:
}
}
}(dogChan)
dogChan <- 1
dogChan <- 2
dogChan <- 3
dogChan <- 4
dogChan <- 5
}
谁能告诉我为什么 case1、case2 出错而 case3 正常? 在 case1 中,我的猜测是 dogChan 没有在 goroutine 中使用,所以它被视为关闭。 在 case2 中,我的猜测是虽然 dogChan 在 goroutine 中传递但它没有在 goroutine 中使用所以它被视为关闭
谁能告诉我为什么 case4 出错而 case5 正常?
为什么您认为 case1
和 case2
会发生这种情况?这些通道旨在充当发送方和接收方之间的同步原语。您有一个发件人在频道上发送,dogChan
但 none 正在接收。
没有接收 goroutine 或 goroutine 上的接收操作,发送方只是阻塞(作为一个无缓冲的通道)
同样的问题 case4
,你在通道上有两个发送,但在 goroutine 上有一个接收。 dogChan <- 2
将永远阻塞。在 case5
中,如果您的目的是从通道读取,只需使用 range
循环来迭代通过它发送的连续值。
Golang 期望程序读取放置在通道中的消息。
消费者 (reader) 需要从通道中排出(读取)所有消息,使用简单的 for-read 或 for-select。通道发送和接收都阻塞,直到发送方和接收方准备就绪。
- case1,case2 = 向通道发送一条消息,阻止等待 reader,读取零条消息
- case4 = 向通道发送一条消息,阻塞等待 reader,reader 不消耗(读取)消息
- case3 = 向通道发送一条消息,从通道消费一条消息,发送方块等待 reader
- case5 = 向通道发送五个消息,消耗所有(五个)消息,每个发送块直到 reader 收到
// for range over channel
for msg := range ch {
// process msg
}
// for select
done := false
for !done {
select {
case msg := <-ch: {
// process msg
}
case ch == nil: {
done = true
}
}
}
// producer should close channel
close(ch)
注:
- 通道可以缓冲,指定通道(队列)大小
- 通道大小默认 = 1(无缓冲),写入器在通道已满时阻塞