例如:
type name struct {
name string
age int
}
func main() {
c := make(chan name)
c <- name{"sfsaf", 1}
a, b := <- c
close(c)
}
结果:
致命错误:所有goroutine都睡着了 - 死锁!
我想通过频道传递值。我该怎么办?
答案 0 :(得分:7)
是的,你可以传递结构。但这不是你的OP中的问题。
当没有接收器准备接收时,您在通道上发送了一个值。这就是导致你陷入僵局的原因。
频道希望receiver
被阻止,等待sender
。这是通过Goroutines完成的。
因此,请将您的发件人包裹在goroutine中,这将不会立即执行。
package main
import (
"fmt"
)
type name struct {
name string
age int
}
func main() {
c := make(chan name)
go func() {
c <- name{"sfsaf", 1}
close(c)
}()
for n := range c {
fmt.Println(n)
}
fmt.Println("channel was closed (all done!).")
}
在操场上看到它:https://play.golang.org/p/uaSuCaB4Ms
这是有效的,因为发件人的goroutine尚未执行。直到当前的goroutine执行被阻止。
我们在for n := range c
循环中被阻止了。这是接收器,坐着等待价值观。 (这是一种常见的模式,使用for循环迭代通道值,因为它将坐下并阻塞,等待值。)
现在我们被阻止等待接收for
循环中的值,现在将执行内联gorouting,以便在频道上发送我们的值。
此外,我们遵循安全做法,并在我们自己和close(c)
频道后进行整理,发出for
循环或select
声明,表示不再发送任何值。 发件人总是关闭,而不是收件人 。这是for
范围循环用于退出for循环的模式,并继续执行其余代码。
作为旁注,你通过传递struct的值来做得很好 - 而不是指针。
如果你传递了一个指针,你必须在对象周围实现一些互斥锁,以防止R / W恐慌。
Do not communicate by sharing memory; instead, share memory by communicating.
坚持在你的频道和goroutines周围传递价值而不是指针,并获得好处。