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