首頁 >後端開發 >Golang >回傳回應後如何優雅地關閉 Go HTTP 伺服器?

回傳回應後如何優雅地關閉 Go HTTP 伺服器?

DDD
DDD原創
2024-10-28 19:12:29220瀏覽

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