首页  >  文章  >  后端开发  >  返回响应后如何优雅地关闭 Go HTTP 服务器?

返回响应后如何优雅地关闭 Go HTTP 服务器?

DDD
DDD原创
2024-10-28 19:12:29145浏览

How to Gracefully Shut Down a Go HTTP Server After Returning a Response?

返回响应后关闭 HTTP 服务器

在此场景中,您构建了一个与 Instagram API 交互的 Go 命令行机器人。要获取访问令牌,您需要启动本地 HTTP 服务器来捕获重定向 URI。然而,您在检索访问令牌后尝试手动关闭服务器时遇到问题。

问题:

关闭服务器时出现“服务器已关闭”和“内存地址无效”错误服务器

分析:

您遇到的错误表明HTTP服务器在所有连接正常关闭之前被过早关闭。这可能是由于 HTTP 处理程序和服务器关闭过程中的异步行为造成的。

解决方案 1:使用 Context.WithCancel:

考虑使用 context.WithCancel 创建一个可以取消的上下文当检索到访问令牌时。将此上下文传递给 HTTP 处理程序,并在上下文关闭时使用 CancelFunc 正常关闭服务器。

<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>

解决方案 2:跨函数使用相同的上下文:

您还可以使用跨多个 HTTP 处理程序和主函数的相同上下文,以确保在服务器应该关闭时通知所有函数。

<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>

结论:

通过使用 context.WithCancel 或传递跨多个函数的相同上下文,您可以确保 HTTP 服务器在所有连接关闭后正常关闭。这将防止您当前遇到的错误。

以上是返回响应后如何优雅地关闭 Go HTTP 服务器?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn