匿名函数中的这个 go-routine 究竟是如何工作的?
How does this go-routine in an anonymous function exactly work?
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 <- message
会阻塞,直到有东西从里面拉出来。然而,在这样包裹之后,它似乎不再阻塞了。我知道它会将此操作发送到后台并照常进行,但我无法理解这不会影响当前的函数调用。
每次调用 send
都会创建一个新的 goroutine,并立即 returns。 (顺便说一句,如果永远不会有错误,就没有理由 return 错误。)如果没有准备好从 chan
(假设它是无缓冲的)。一旦消息被 chan
读取,goroutine 将继续,但由于它什么都不做,它就会简单地结束。
我应该指出,没有 匿名 goroutine 这样的东西。 Goroutines 根本没有标识符(除了一个你应该只用于调试目的的数字)。你有一个 匿名函数 ,你把 go
关键字放在前面,导致它在一个单独的 goroutine 中 运行。
对于您想要的阻塞发送函数,只需使用:
func (s *server) send(m *message) {
s.outgoingMessageChan <- message
}
但是,我看不出这个函数有任何意义(尽管它是内联的并且与不使用函数一样高效)。
我怀疑您可能在从 chan 读取任何内容之前多次调用 send
。在这种情况下,将创建许多新的 goroutines(每次调用 send
),它们都会阻塞。每次从一个 chan 中读取时,都会解除阻塞传递它的值,并且该 goroutine 将终止。这样做只是在创建一个低效的缓冲机制。此外,如果 send
以比从 chan 读取值更快的速度长时间调用,那么您最终将 运行 内存不足。更好的方法是使用缓冲的 chan(并且没有 goroutines),一旦它(chan)完全发挥“back-pressure”在产生消息的任何东西上。
还有一点就是函数名main
用来标识程序的入口点。请为上面的第二个函数使用另一个名称。它似乎也应该是一个方法(使用 s *server
接收器)而不是一个函数。
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 <- message
会阻塞,直到有东西从里面拉出来。然而,在这样包裹之后,它似乎不再阻塞了。我知道它会将此操作发送到后台并照常进行,但我无法理解这不会影响当前的函数调用。
每次调用 send
都会创建一个新的 goroutine,并立即 returns。 (顺便说一句,如果永远不会有错误,就没有理由 return 错误。)如果没有准备好从 chan
(假设它是无缓冲的)。一旦消息被 chan
读取,goroutine 将继续,但由于它什么都不做,它就会简单地结束。
我应该指出,没有 匿名 goroutine 这样的东西。 Goroutines 根本没有标识符(除了一个你应该只用于调试目的的数字)。你有一个 匿名函数 ,你把 go
关键字放在前面,导致它在一个单独的 goroutine 中 运行。
对于您想要的阻塞发送函数,只需使用:
func (s *server) send(m *message) {
s.outgoingMessageChan <- message
}
但是,我看不出这个函数有任何意义(尽管它是内联的并且与不使用函数一样高效)。
我怀疑您可能在从 chan 读取任何内容之前多次调用 send
。在这种情况下,将创建许多新的 goroutines(每次调用 send
),它们都会阻塞。每次从一个 chan 中读取时,都会解除阻塞传递它的值,并且该 goroutine 将终止。这样做只是在创建一个低效的缓冲机制。此外,如果 send
以比从 chan 读取值更快的速度长时间调用,那么您最终将 运行 内存不足。更好的方法是使用缓冲的 chan(并且没有 goroutines),一旦它(chan)完全发挥“back-pressure”在产生消息的任何东西上。
还有一点就是函数名main
用来标识程序的入口点。请为上面的第二个函数使用另一个名称。它似乎也应该是一个方法(使用 s *server
接收器)而不是一个函数。