MST

星途 面试题库

面试题:Go的HTTP服务中如何优雅处理异常

假设你正在开发一个Go语言的HTTP服务器,在处理HTTP请求的过程中,可能会出现各种业务逻辑错误和系统错误。请描述你会如何设计一个通用的异常处理机制,确保服务在发生异常时能够返回合适的HTTP状态码和错误信息,同时不影响其他请求的正常处理,并给出关键代码示例。
22.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 设计思路

    • 中间件(Middleware):使用中间件来捕获处理函数中抛出的异常。这样可以在不修改每个处理函数具体逻辑的情况下,统一处理异常。
    • 自定义错误类型:定义自定义错误类型,以便区分业务逻辑错误和系统错误,并根据不同类型返回不同的HTTP状态码。
    • 日志记录:在捕获异常时记录详细的日志,方便调试和排查问题。
  2. 关键代码示例

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
)

// 自定义错误类型
type BusinessError struct {
    ErrorMessage string `json:"error_message"`
}

func (be BusinessError) Error() string {
    return be.ErrorMessage
}

// 异常处理中间件
func errorHandler(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        defer func() {
            if err := recover(); err!= nil {
                // 记录异常日志
                log.Printf("Panic occurred: %v", err)
                var statusCode int
                var errorMsg string
                switch err := err.(type) {
                case BusinessError:
                    statusCode = http.StatusBadRequest
                    errorMsg = err.Error()
                default:
                    statusCode = http.StatusInternalServerError
                    errorMsg = "Internal Server Error"
                }
                w.WriteHeader(statusCode)
                response := map[string]string{"error": errorMsg}
                json.NewEncoder(w).Encode(response)
            }
        }()
        next.ServeHTTP(w, r)
    })
}

// 模拟业务处理函数
func handleRequest(w http.ResponseWriter, r *http.Request) {
    // 模拟业务逻辑错误
    if r.URL.Query().Get("error") == "business" {
        panic(BusinessError{ErrorMessage: "Business logic error"})
    }
    // 模拟系统错误
    if r.URL.Query().Get("error") == "system" {
        panic(fmt.Errorf("System error"))
    }
    w.Write([]byte("Request processed successfully"))
}

func main() {
    http.Handle("/", errorHandler(http.HandlerFunc(handleRequest)))
    log.Fatal(http.ListenAndServe(":8080", nil))
}

在上述代码中:

  • BusinessError 是自定义的业务逻辑错误类型。
  • errorHandler 是异常处理中间件,使用 deferrecover 来捕获处理函数中抛出的异常。根据异常类型设置不同的HTTP状态码,并返回相应的错误信息。同时记录异常日志。
  • handleRequest 是模拟的业务处理函数,根据URL参数模拟不同类型的异常。
  • main 函数中,将 errorHandler 应用到 handleRequest 上,这样在处理HTTP请求时,如果发生异常,errorHandler 会捕获并处理。