我可以在 go 中使用 make(chan someStruct) 吗?
Posted
技术标签:
【中文标题】我可以在 go 中使用 make(chan someStruct) 吗?【英文标题】:Can I use make(chan someStruct) in go? 【发布时间】:2017-11-12 19:31:20 【问题描述】:例如:
type name struct
name string
age int
func main()
c := make(chan name)
c <- name"sfsaf", 1
a, b := <- c
close(c)
结果:
致命错误:所有 goroutine 都处于休眠状态 - 死锁!
我想通过通道传递值。我该怎么办?
【问题讨论】:
Channel 用于并发函数之间的通信。在您的示例中,写入和读取操作不是并发的,从而导致死锁。在goroutine
内执行读取或写入,例如go func() c <- name"sfsaf", 1 ()
.
***.com/questions/36505012/… 的可能重复项。
@CeriseLimón 这不是一个重复的问题。那个没有显示如何使用make(chan somestruct)
。
@putu 谢谢,我会试试的。你怎么看make(chan non-empty-struct)
没有理由close
频道,除非您发出信号表明您的接收将不再有值(例如使用for range
循环)。请参阅下面发布的我的答案,更新了有关如何使用频道的更多详细信息。
【参考方案1】:
是的,您可以传递结构。但这不是您的 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
range 循环用于退出 for 循环并继续执行其余代码的模式。
顺便说一句,您通过传递结构的值而不是指针做得很好。
如果你传递了一个指针,你必须在对象周围实现一些互斥锁来防止 R/W 恐慌。
Do not communicate by sharing memory; instead, share memory by communicating.
坚持在通道和 goroutine 周围传递值,而不是指针,并从中获益。
【讨论】:
感谢您的回答。我想知道如何获取结构的元素。在这个例子中,我想得到 我知道了,应该使用 ( 你怎么能保证上面的代码总是有效的?换句话说,for循环上面的goroutine在命中for循环后会被执行的保证是什么? @user1870400 这是语言的设计。由于 Golang 在设计上是一种程序性(例如命令式)语言,因此它按顺序执行操作。在 Golang 规范中(找不到链接 atm),go func()
指令被推迟执行,直到当前 goroutine 被阻塞 - 这发生在上面列出的代码中的 for n := range c
操作上。为了缓解混乱,每个操作,包括main()
,都在一个goroutine中执行。您的整个应用程序在单个 goroutine 中运行,直到您调用 go func()
- 现在您将拥有两个 goroutine。以上是关于我可以在 go 中使用 make(chan someStruct) 吗?的主要内容,如果未能解决你的问题,请参考以下文章