為你的 Go API 添加日志記錄和錯誤處理中間件
在構建 Go API 時,日志記錄和錯誤處理是至關重要的組成部分,它們可以幫助你調試代碼、監控 API 行為并為用戶提供友好的錯誤提示。中間件提供了一種優雅的方式來實現這些功能,它允許你在請求到達你的 API 端點之前攔截請求并執行一些操作。
本文將引導你逐步添加日志記錄和錯誤處理中間件到你的 Go API 中,使你的 API 更加健壯、易于維護和用戶友好。
什么是中間件?
中間件就像你最喜歡的夜總會里的保安,它會在請求到達你的 API 端點之前攔截請求。你可以使用中間件來檢查身份驗證(比如我們在 JWT 中所做的那樣)、記錄信息或在出現錯誤時進行處理。
今天,我們將構建一個中間件,它可以:
- 記錄:每個傳入請求,以便我們知道誰在敲打我們的 API 的門。
- 處理錯誤:優雅地處理錯誤,這樣你的用戶就不會看到那些難看的 500 錯誤。
讓我們深入研究吧!
第一步:創建日志記錄中間件
日志記錄是你調試和了解 API 中發生的事情時最好的朋友。我們將創建一個中間件,它記錄每個傳入請求——方法、URL 和所用時間。
import (
"log"
"net/http"
"time"
)
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// 記錄方法和請求的 URL
log.Printf("Started %s %s", r.Method, r.URL.Path)
// 調用鏈中的下一個處理程序
next.ServeHTTP(w, r)
// 記錄所用時間
log.Printf("Completed in %v", time.Since(start))
})
}這段代碼定義了一個名為 loggingMiddleware 的函數,它接受一個 http.Handler 作為參數,并返回一個新的 http.Handler。這個新處理程序包含一個匿名函數,它會在每個請求到達時執行。在函數中,我們首先記錄了請求的開始時間,然后記錄了請求的方法和 URL。接下來,我們調用 next.ServeHTTP 將請求傳遞給鏈中的下一個處理程序。最后,我們記錄了請求的處理時間。
第二步:錯誤處理中間件
讓我們談談錯誤。錯誤會發生,對吧?但是,與其讓它們導致崩潰或發送模糊的錯誤消息,不如讓我們優雅地處理它們。
func errorHandlingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
// 記錄錯誤并發送用戶友好的消息
log.Printf("Error occurred: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
})
}這段代碼定義了一個名為 errorHandlingMiddleware 的函數,它接受一個 http.Handler 作為參數,并返回一個新的 http.Handler。這個新處理程序包含一個匿名函數,它會在每個請求到達時執行。在函數中,我們使用 defer 關鍵字來確保在函數返回之前執行一個匿名函數。這個匿名函數使用 recover() 函數來捕獲任何恐慌,并記錄錯誤信息,然后向客戶端發送一個 500 錯誤。
第三步:在你的 API 中集成中間件
現在我們已經構建了日志記錄和錯誤處理中間件,讓我們將它們連接到我們的 API。我們將全局應用它們,這樣每個請求都會被記錄,并且錯誤會被捕獲。
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
// ... 其他代碼 ...
func main() {
// ... 其他代碼 ...
r := mux.NewRouter()
// 全局應用中間件
r.Use(loggingMiddleware)
r.Use(errorHandlingMiddleware)
// ... 其他代碼 ...
fmt.Println("Server started on port :8000")
log.Fatal(http.ListenAndServe(":8000", r))
}在 main 函數中,我們首先創建了一個 mux.NewRouter 對象,它用于路由請求。然后,我們使用 r.Use 函數全局應用了 loggingMiddleware 和 errorHandlingMiddleware。這樣,所有請求都會經過這兩個中間件。
第四步:測試它
為了確保一切正常,啟動你的 API:
go run main.go現在,嘗試訪問你的任何端點(例如 /books)并檢查你的終端。你應該看到類似以下的日志:
Started GET /books
Completed in 1.2ms如果出現錯誤,你會看到:
Error occurred: some error details但是,你的用戶只會看到一條干凈的“500 內部服務器錯誤”消息。??
為什么這很重要?
- 日志記錄有助于你跟蹤錯誤和監控 API 的行為。如果出現問題,你會確切地知道哪個端點被訪問以及請求花費了多長時間。
- 錯誤處理可以防止你的 API 在出現意外情況時崩潰。相反,它會優雅地恢復并向客戶端發送一條清晰的錯誤消息。




























