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

Concurrency 当处理第三方代码时,如何知道Go中会同时发生什么,concurrency,go,Concurrency,Go,假设我在我的Web服务器中使用了一个虚构的包,名为github.com/john/jupiterDb,用于连接我在Jupiter上托管的数据库 当有人向我的服务器发出请求时,我希望将请求主体存储在我的Jupiter DB中。所以我有一些类似这样的代码: http.HandleFunc("/SomeEvent", registerSomeEvent) 在我的registerSomeEvent处理程序中,我要执行以下操作: func registerSomeEvent(w http.Respons

假设我在我的Web服务器中使用了一个虚构的包,名为
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例程,以确保这些函数立即返回且无阻塞。这是否意味着我需要检查我使用的每个包的源代码,以确保正确使用并发性


我应该用一个额外的go例程来包装它,还是应该相信维护人员已经为我完成了这项工作?这让我感觉我没有能力把一个包裹当作一个黑匣子,或者我遗漏了什么?

我只需要阅读正文并将其发送到一个频道。一组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!")
}
var reqPayloadChannel=make(chan字符串,100)
func jupiter_worker(){
对于有效负载:=范围reqPayloadChannel{
jupiterDb.Insert(有效负载)//需要一些时间!
}
}
func registerSomeEvent(w http.ResponseWriter,r*http.Request){

reqPayloadChannel没有一个健全的库会以静默方式将调用(如
Insert
)作为后台,然后返回而不出错,除非它非常明确地记录了原因。更不用说,您也需要处理代码中的错误值。Go中的惯例通常是“您只需阻塞”(提到了,我想我也听过一位Go团队成员,可能是Andrew Gerrand说的)。如果是异步的,文档应该涵盖这一点。正如JimB所指出的,这可以说是数据库插入调用在任何语言中工作的唯一明智的方法,因为DBs必须保证您的内容在某个时候都被编写好,然后插入(或假设的承诺)是最明显的一点。@two如果它阻塞了,我的服务器可能会没有响应,因为我正在等待Jupiter的答复。或者你是说在goroutine中阻塞?@mattharrison,不,你的服务器不会没有响应,因为每个web请求都在一个新的goroutine中处理。这意味着只有当前运行db调用的goroutine将阻止,所有其他请求将继续愉快地进行。@MattHarrison我认为您和Ralph只是在谈论相同的行为。Ralph说,较大的服务器进程将在Insert运行时响应其他请求(因此从这个意义上讲,它不是“无响应”)。您的意思是,如果您没有明确说明插入内容的背景,则对该请求的响应会很慢。这两种说法都是准确的。