【问题标题】:How does this go-routine in an anonymous function exactly work?匿名函数中的这个 go-routine 究竟是如何工作的?
【发布时间】:2020-09-27 19:25:38
【问题描述】:
func (s *server) send(m *message) error {
    go func() {
        s.outgoingMessageChan <- message
    }()
    return nil
}

func main(s *server) {
    for {
        select {
        case <-someChannel:
            // do something
        case msg := <-s.outGoingMessageChan:
            // take message sent from "send" and do something
        }
    }
}

我在另一个函数中退出 s.outgoingMessageChan,在使用匿名 go 函数之前,对该函数的调用通常会阻塞 - 这意味着无论何时调用 send,s.outgoingMessageChan &lt;- message 都会阻塞,直到有东西退出其中。然而,像这样包裹它之后,它似乎不再阻塞了。我知道它会将此操作发送到后台并照常进行,但我无法理解这不会影响当前的函数调用。

【问题讨论】:

  • 没错,s.outgoingMessageChan &lt;- message 仍然阻塞,但现在它在自己的 goroutine 中运行,这不会影响您的主 goroutine。
  • 如果它停止阻塞,但send 不再被调用会怎样?
  • message 被推送到 s.outgoingMessageChan 并且匿名 goroutine 终止。尝试重新访问相关的go tour parts,也许?理解 goroutine 对编写好的 go 语言至关重要。

标签: go goroutine


【解决方案1】:

每次调用send 都会创建一个新的goroutine,并立即返回。 (顺便说一句,如果永远不会出现错误,则没有理由返回错误。)如果没有准备好从 chan 读取(假设它没有缓冲),goroutine(它有自己的执行“线程”)将阻塞.一旦从chan 读取消息,goroutine 将继续,但由于它不执行任何其他操作,它将简单地结束。

我应该指出,没有匿名 goroutine 这样的东西。 Goroutines 根本没有标识符(除了一个只能用于调试目的的数字)。您有一个匿名函数,您将go 关键字放在前面,使其在单独的goroutine 中运行。

如果你想阻止发送功能,那么只需使用:

func (s *server) send(m *message) {
    s.outgoingMessageChan <- message
}

但是,我看不到这个函数的任何意义(尽管它会被内联并且与不使用函数一样有效)。

我怀疑你可能会在从 chan 读取任何内容之前多次调用send。在这种情况下,将创建许多新的 goroutines(每次调用 send),它们都会阻塞。每次从其中读取 chan 时,都会解除阻止传递其值的阻塞,并且该 goroutine 将终止。这样做你只是在创建一个低效的缓冲机制。此外,如果send 以比从chan 中读取的值更快的速度长时间调用,那么您最终将耗尽内存。更好的办法是使用缓冲的 chan(并且没有 goroutine),一旦它(chan)变满,就会对产生消息的任何东西施加“背压”。

另外一点是函数名main用来标识程序的入口点。请为上面的第二个函数使用另一个名称。看起来它应该是一个方法(使用s *server接收器)而不是一个函数。

【讨论】:

  • 我不能在这种情况下使用缓冲通道,有什么更好的方法来做到这一点?我的第一个直觉也是缓冲通道。
  • 如果你想缓冲值但不使用缓冲通道(为什么不呢?)那么你必须以某种方式缓冲它们,例如,通过存储在一个切片中或者你可以像在你的原始帖子中那样做只要您确定消息被消耗,从长远来看,它们比它们产生的更快。我希望这个答案对你有用,但如果没有更多信息,我不能更具体。关于你正在尝试做的事情。
  • 我不能使用缓冲频道,因为我的作业不允许使用它::p 但我明白你的意思。谢谢你的回复,内容很丰富!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
  • 2021-01-27
相关资源
最近更新 更多