我正在加速golang的频道。根据{{3}},
频道是您可以通过其发送和接收的类型管道 使用通道运算符的值< - 。
我明白了。我理解如何使用go例程的例子。我尝试了一个非常简单的例子。它导致程序陷入僵局。忽略这个程序的无意义,请你告诉我为什么这个问题陷入僵局?
package main
import "fmt"
func main() {
c := make(chan int)
c <- 17
fmt.Println(<- c)
}
引用文档补充说明
默认情况下,发送和接收阻止,直到另一方准备好。
好的,在上面的示例中,遇到c <- 17
时,发件人(主例程) 准备发送。所以不应该执行。随后Println
应该能够消耗频道。
如果将c <- 17
替换为
go func() { c <- 17 } ()
只是想了解为什么这是必要的。
答案 0 :(得分:5)
默认情况下,发送和接收阻止,直到另一方准备好。
确切地说:由于没有等待接收的常规例程,发送被阻止,并且您的程序陷入僵局。发送操作不会被跳过,因为没有人等待接收。
如果你想进行非阻塞发送,你可以在带有默认情况的select语句中使用send运算符:
select {
case c <- 17:
default:
}
答案 1 :(得分:3)
The Go Programming Language Specification
通道提供了一种同时执行函数的机制 通过发送和接收指定元素的值进行通信 类型。
可以使用内置的新的初始化通道值 function make,它采用通道类型和可选容量 作为参数:
make(chan int, 100)
容量(以元素数量)设置缓冲区的大小 这个频道。如果容量为零或不存在,则通道为 无缓冲和通信只有当发送者和发送者都成功时才会成功 接收器准备好了。否则,通道被缓冲 如果缓冲区未满,则通信成功而不会阻塞 (发送)或不空(接收)。零通道永远不会准备好 通信。
你问:为什么golang中的频道需要一个常规程序?
Go通道不需要goroutine。成功发送仅需要准备好的接收器或未满的缓冲器。例如,使用缓冲通道
package main
import "fmt"
func main() {
c := make(chan int, 1)
c <- 17
fmt.Println(<-c)
}
输出:
17
您的示例失败,因为它尝试发送没有准备接收器的无缓冲通道。
package main
import "fmt"
func main() {
c := make(chan int)
c <- 17
fmt.Println(<-c)
}
输出:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/home/peter/gopath/src/sri.go:7 +0x59
@Tim Cooper's proposed solution有同样的错误。
package main
import "fmt"
func main() {
c := make(chan int)
select {
case c <- 17:
default:
}
fmt.Println(<-c)
}
输出:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/home/peter/gopath/src/tim.go:11 +0x8a