在处理第三方代码时,如何知道Go中会同时发生什么事情

huangapple go评论75阅读模式
英文:

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 &lt;- r.Body.ReadAll()
	fmt.Fprint(w, &quot;Thanks!&quot;)
}

Next steps are to setup the working group and to handle the case when the jupiter channel is full due to very slow clients.

huangapple
  • 本文由 发表于 2014年5月29日 05:54:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/23922529.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定