假设我在我的网络服务器github.com/john/jupiterDb
中使用了一个虚构的软件包,我用它来连接我在Jupiter上托管的数据库。
当有人向我的服务器发出请求时,我想将请求的正文存储在我的Jupiter DB中。所以我有一些像这样的代码:
http.HandleFunc("/SomeEvent", registerSomeEvent)
在我的registerSomeEvent
处理程序中,我想这样做:
func registerSomeEvent(w http.ResponseWriter, r *http.Request) {
jupiterDb.Insert(r.Body) // Takes a while!
fmt.FPrint(w, "Thanks!")
}
现在显然我不想等到木星往返感谢我的用户。所以显而易见的Go事情是将Insert
调用包装在一个go例程中。
但是,使用冗长IO的软件包的创建者通常会在软件包中使用go例程来确保这些函数立即返回并且是非阻塞的。这是否意味着我需要检查我使用的每个包的源代码,以确保我正确使用并发?
我是否应该将其包装在一个额外的例行程序中,或者我是否应该相信维护者已经为我完成了这项工作?这样的感觉就像我没有能力将包装当作黑盒子,或者我错过了什么?
答案 0 :(得分:2)
我会读取正文并将其发送到频道。一组goroutine将从频道中读取并向木星发送有效载荷。
var reqPayloadChannel = make(chan string, 100)
func jupiter_worker() {
for payload := range reqPayloadChannel {
jupiterDb.Insert(payload) // Takes a while!
}
}
func registerSomeEvent(w http.ResponseWriter, r *http.Request) {
reqPayloadChannel <- r.Body.ReadAll()
fmt.Fprint(w, "Thanks!")
}
接下来的步骤是设置工作组,并在由于客户端非常慢的情况下,当jupiter通道已满时处理该情况。