Answer the question
In order to leave comments, you need to log in
How to work with Context correctly?
Good afternoon. I have a function:
func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
p := getProviders(w, r)
defer p.Close()
ctx, cancel := context.WithTimeout(context.Background(), config.Read().HTTP.Timeout.Request*time.Second)
defer cancel()
h, isExist := nodePathGet(router.getBaseNode(r.Method), r.RequestURI)
if !isExist {
router.Errors.PageNotFound(ctx, p)
} else {
go func() {
router.middlewareHandler(h)(ctx, p)
cancel()
}()
}
<-ctx.Done()
if ctx.Err() == nil {
if ctx.Err() == context.DeadlineExceeded {
log.Println(r.Method, r.RequestURI, "error request timeout")
router.Errors.RequestTimeout(ctx, p)
}
}
}
router.middlewareHandler(h)(ctx, p)
runs longer than the set timeout, it triggers defer p.Close()
which frees the memory, and then the routine tries to write something there and everything falls with a panic. Answer the question
In order to leave comments, you need to log in
Firstly, it is better to take the context not from Background, but from the http request. Thus, you will correctly handle the situation when the connection with the client is broken and you no longer need to process the request (the context will be canceled).
ctx, cancel := context.WithTimeout(r.Context(), config.Read().HTTP.Timeout.Request*time.Second)
sync.WaitGroup
. <-ctx.Done()
inside the function you provided occurs before the same reading of the channel inside the router.middlewareHandler(h) function. Therefore, you need to wait not for the cancellation of the context, but for the completion of the goroutine. if ctx.Err() != nil {
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question