为什么golang中的通道需要一个常规程序?

Sri*_*ran 1 go

我正准备加速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)

只是想了解为什么这是必要的.

Tim*_*per 5

默认情况下,发送和接收阻塞,直到另一方准备好.

确切地说:因为没有等待接收的例程,发送被阻止,并且程序死锁.发送操作不会被跳过,因为没有人等待接收.

如果要执行非阻塞发送,则可以在具有默认情况的select语句中使用send运算符:

select {
case c <- 17:
default:
}
Run Code Online (Sandbox Code Playgroud)

  • 在无缓冲通道中,在另一个例程读取该值之前,该值无处可去。在问题中的单线程、无缓冲示例中,写入通道和读取通道之间的 17 会在哪里?如果没有缓冲区,则在执行下一行之前没有任何地方可以保存该值。 (3认同)

pet*_*rSO 5

Go编程语言规范

频道类型

通道提供了一种机制,用于通过发送和接收指定元素类型的值来同时执行功能以进行通信。

可以使用内置函数make来创建一个新的初始化通道值,该函数将通道类型和可选容量作为参数:

make(chan int, 100)
Run Code Online (Sandbox Code Playgroud)

容量(以元素数为单位)设置通道中缓冲区的大小。如果容量为零或不存在,则通道没有缓冲,并且仅在发送方和接收方都准备就绪时,通信才能成功。否则,如果缓冲区未满(发送)或不为空(接收),则通道将被缓冲,并且通信将成功进行而不会阻塞。零通道永远不会准备好进行通信。


您问:为什么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)