英文:
Golang 'defer' causing delay in sending(receiving) API response
问题
我创建了一个API,在处理请求并发送响应后,启动一个后台goroutine来记录一些消息。我使用了'defer'来在处理API请求后执行goroutine。
以下是代码片段:
发送响应的伪代码:
{
...
res.Header().Add("Content-Type", "application/json")
json.NewEncoder(res).Encode(response)
}
响应结构体:
type Response struct {
StatusCode int16 `json:"statusCode"`
Message string `json:"message"`
}
API主体:
{
...
defer logMsgs()
sendAPIResponse()
return
}
记录消息的伪代码:
func logMsgs(){
time.Sleep(10*time.Seconds)
wg := sync.Waitgroup{}
wg.Add(1)
go func(){
for i = 1 to 10
print(i)
wg.Done()
}()
wg.Wait()
}
期望的结果是在收到API响应后,经过几秒钟(这里是10秒),从1到10打印出'i'的值。
但实际结果是在10秒后才收到API响应。
根据我的理解,defer函数在周围(或当前/封闭)函数终止或返回后调用。
所以我必须先收到API响应,然后才能记录'i'的值。但在我的情况下,我在一些秒钟(10秒)后才收到响应。如果'i'的值很大,这将是一个重大问题。
如果有人能解释这种异常行为并提供可能的解决方案,将会很有帮助。谢谢。
英文:
I have created an API, which after processing the request sends a response and starts a background goroutine which logs some messages. I have used 'defer' to execute goroutine after the API request has been handled.
Following are the code snippets:
sendResponse Pseudocode:
{
...
res.Header().Add("Content-Type", "application/json")
json.NewEncoder(res).Encode(response)
}
Response struct:
type Response struct {
StatusCode int16 `json:"statusCode"`
Message string `json:"message"`
}
API Body:
{
...
defer logMsgs()
sendAPIResponse()
return
}
logMsgs Pseudocode:
func logMsgs(){
time.Sleep(10*time.Seconds)
wg := sync.Waitgroup{}
wg.Add(1)
go func(){
for i = 1 to 10
print(i)
wg.Done()
}()
wg.Wait()
}
Expected Outcome is to receive the API response and after few seconds(here 10s) value of 'i' is printed from 1 to 10.
But in Actual Outcome, API response is received after 10s.
As per my understanding defer functions are called after the surrounding (or current/enclosing) function terminates or returns.
So I must first receive the API response and later values of 'i' must be logged. But in my case I am receiving the response after some seconds(10s) are elapsed. This would be a major issue if value of 'i' is quite large.
It will be helpful if someone explains this abnormal behavior and provides possible solutions.
Thanks
答案1
得分: 1
我已经使用了defer
来在处理完API请求后执行goroutine。
defer
并不会启动一个goroutine,它会在调用的goroutine上执行延迟函数。而且很有可能响应被缓存,直到从处理程序返回之前写入的数据才不会被刷新。
如果你想在一个新的goroutine中执行日志记录,可以使用go
关键字,像这样:
defer func() {
go logMsgs()
}()
sendAPIResponse()
return
但是请注意,在处理程序返回后,启动的goroutine无法访问请求和响应特定的对象,因为它们可能会被重用于新的请求。所以在处理程序返回后,保存/传递日志记录器所需的所有内容,以便安全地在处理程序返回后使用它们。
英文:
> I have used 'defer' to execute goroutine after the API request has been handled.
defer
does not launch a goroutine. It executes the deferred function on the calling goroutine. And it's very much possible that the response is cached and data written to it is not flushed until you return from your handler.
If you want to execute the logging in a new goroutine, use the go
keyword like this:
defer func() {
go logMsgs()
}()
sendAPIResponse()
return
Note however that after returning from the handler, launched goroutines cannot access request and response specific objects as they may be reused for new requests. So save / pass everything that the logger needs in order to safely use them after returning from the handler.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论