惯用Golang goroutines

Aid*_*ell 16 go

在Go中,如果我们的类型具有启动某些循环机制的方法(轮询A并永远执行B),最好将其表达为:

// Run does stuff, you probably want to run this as a goroutine
func (t Type) Run() {
    // Do long-running stuff
}
Run Code Online (Sandbox Code Playgroud)

并记录这可能是想作为goroutine启动(并让调用者处理)

或者从调用者隐藏它:

// Run does stuff concurrently
func (t Type) Run() {
   go DoRunStuff()
}
Run Code Online (Sandbox Code Playgroud)

我是Go的新手,并且不确定惯例是否说调用者前缀为'go'或者当代码设计为运行异步时为他们执行.

我目前的观点是我们应该记录并给呼叫者一个选择.我的想法是,在Go中,并发性实际上并不是暴露接口的一部分,而是使用它的属性.这是正确的吗?

kwo*_*lfe 10

我对此有你的看法,直到我开始编写一个我希望并发的Web服务的适配器.我有一个go例程,必须启动它来解析从Web调用返回到通道的结果.绝对没有这种API可以在不将其用作go例程的情况下工作的情况.

然后我开始查看net/http这样的软件包.该包中存在强制并发.在接口级别记录它应该能够并发使用,但是默认实现自动使用go例程.

因为Go的标准库通常会在自己的包中触发go例程,所以我认为如果你的包或API保证它,你可以自己处理它们.


zmb*_*zmb 9

我目前的观点是我们应该记录并给呼叫者一个选择.

我倾向于同意你的观点.

由于Go使得同时运行代码变得如此容易,因此您应该尽量避免API中的并发性(这会迫使客户端同时使用它).相反,创建一个同步API,然后客户端可以选择同步或同时运行它.

几年前的一次演讲中讨论了这个问题:十二个最佳实践

特别是,幻灯片26显示的代码更像您的第一个示例.

我会将net/http包视为异常,因为在这种情况下,并发性几乎是强制性的.如果包在内部不使用并发,那么客户端代码几乎肯定必须.例如,http.Client(据我所知)不会启动任何goroutines.只有服务器这样做.

在大多数情况下,它将成为调用方代码的一行:

go Run() 要么 StartGoroutine()

同步API并不难同时使用,并为调用者提供了更多选项.