Home >Backend Development >Golang >How to Gracefully Shut Down a Go HTTP Server After Returning a Response?
In this scenario, you have built a Go command-line bot that interacts with the Instagram API. To obtain the access token, you start a local HTTP server to capture the redirect URI. However, you encounter an issue while attempting to manually shut down the server after retrieving the access token.
"Server Closed" and "Invalid Memory Address"Errors Occur When Shutting Down the Server
The errors you encounter indicate that the HTTP server is being shut down prematurely before all connections are closed gracefully. This can occur due to asynchronous behavior in the HTTP handler and the server shutdown process.
Consider using context.WithCancel to create a context that can be canceled when the access token is retrieved. Pass this context to the HTTP handler and use CancelFunc to gracefully shut down the server when the context is closed.
<code class="go">package main import ( "context" "io" "log" "net/http" ) func main() { ctx, cancel := context.WithCancel(context.Background()) http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Bye\n") cancel() }) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hi\n") }) srv := &http.Server{Addr: ":8080"} go func() { err := srv.ListenAndServe() if err != http.ErrServerClosed { log.Println(err) } }() <-ctx.Done() err := srv.Shutdown(context.Background()) if err != nil { log.Println(err) } log.Println("done.") }</code>
You can also use the same context across multiple HTTP handlers and the main function to ensure that all functions are notified when the server should shut down.
<code class="go">package main import ( "context" "io" "log" "net/http" ) func main() { ctx, cancel := context.WithCancel(context.Background()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hi\n") }) http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Bye\n") cancel() }) srv := &http.Server{Addr: ":8080"} go func() { if err := srv.ListenAndServe(); err != nil { log.Printf("Httpserver: ListenAndServe() error: %s", err) } }() <-ctx.Done() if err := srv.Shutdown(ctx); err != nil && err != context.Canceled { log.Println(err) } log.Println("done.") }</code>
By using context.WithCancel or passing the same context across multiple functions, you can ensure that the HTTP server shuts down gracefully after all connections have been closed. This will prevent the errors you are currently encountering.
The above is the detailed content of How to Gracefully Shut Down a Go HTTP Server After Returning a Response?. For more information, please follow other related articles on the PHP Chinese website!