英文:
How to know what will happen concurrently in Go when dealing with 3rd party code
问题
假设我在我的Web服务器中使用一个名为github.com/john/jupiterDb
的虚构包来连接我的Jupiter数据库。
当有人向我的服务器发出请求时,我想将请求的主体存储在我的Jupiter数据库中。所以我有以下代码:
http.HandleFunc("/SomeEvent", registerSomeEvent)
在我的registerSomeEvent
处理程序中,我想要这样做:
func registerSomeEvent(w http.ResponseWriter, r *http.Request) {
jupiterDb.Insert(r.Body) // 这个操作需要一些时间!
fmt.FPrint(w, "Thanks!")
}
显然,我不想等待与Jupiter的往返以感谢我的用户。所以在Go中,明显的做法是将Insert
调用包装在一个go程中。
但是,通常情况下,执行耗时IO操作的包的创建者会在包中使用go程,以确保这些函数立即返回并且是非阻塞的。这是否意味着我需要检查我使用的每个包的源代码,以确保我正确地使用并发?
我应该无论如何将其包装在额外的go程中,还是应该相信维护者已经为我完成了这项工作?这感觉让我对待包的能力变得更少,或者我有什么遗漏的地方吗?
英文:
Let's say I'm using a fictional package in my webserver called github.com/john/jupiterDb
that I'm using to connect to my database hosted on Jupiter.
When someone makes a request to my server, I want to store the body of the request in my Jupiter DB. So I have some code like this:
http.HandleFunc("/SomeEvent", registerSomeEvent)
And in my registerSomeEvent
handler I want to do this:
func registerSomeEvent(w http.ResponseWriter, r *http.Request) {
jupiterDb.Insert(r.Body) // Takes a while!
fmt.FPrint(w, "Thanks!")
}
Now obviously I don't want to wait for the round trip to Jupiter to thank my user. So the obvious Go thing to do is to wrap that Insert
call in a go routine.
But oftentimes creators of packages that do lengthy IO will use go routines in the package to ensure these functions return immediately and are non-blocking. Does this mean I need to check the source for every package I use to make sure I'm using concurrency correctly?
Should I wrap it in an extra go routine anyway or should I trust the maintainer has already done the work for me? This feels to make like I have less ability to treat a package as a black box, or am I missing something?
答案1
得分: 2
我只会翻译你提供的内容,以下是翻译结果:
我只会读取请求体并将其发送到一个通道。一组goroutine将从通道中读取并将有效载荷发送到jupiter。
var reqPayloadChannel = make(chan string, 100)
func jupiter_worker() {
for payload := range reqPayloadChannel {
jupiterDb.Insert(payload) // 需要一些时间!
}
}
func registerSomeEvent(w http.ResponseWriter, r *http.Request) {
reqPayloadChannel <- r.Body.ReadAll()
fmt.Fprint(w, "谢谢!")
}
下一步是设置工作组,并处理由于非常慢的客户端导致jupiter通道已满的情况。
英文:
I would just read the body and send it to a channel. A group of goroutines will be reading from the channel and send to jupiter the payload.
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!")
}
Next steps are to setup the working group and to handle the case when the jupiter channel is full due to very slow clients.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论