在Golang的Web接口开发中,合理的错误处理能让接口返回更规范,也方便后续问题排查。下面介绍几种常用的Web接口错误处理方式,结合实际场景说明实现逻辑。

基础的错误返回方式
使用标准库net/http开发接口时,最直接的方式是在处理函数内部判断错误后,通过http.Error返回错误信息。这种方式适合简单的接口场景,能快速返回错误状态和描述。
package main
import (
"fmt"
"net/http"
)
func getUserHandler(w http.ResponseWriter, r *http.Request) {
// 模拟查询用户时的错误
err := fmt.Errorf("用户不存在")
if err != nil {
// 返回400状态码和错误信息
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 正常返回逻辑
w.Write([]byte("用户数据"))
}
func main() {
http.HandleFunc("/user", getUserHandler)
http.ListenAndServe(":8080", nil)
}
自定义错误类型统一返回格式
为了让接口错误返回格式统一,比如都包含错误码、错误信息、请求ID等字段,可以自定义错误类型,同时封装统一的响应方法。这样所有接口的错误返回结构都一致,前端处理起来更方便。
package main
import (
"encoding/json"
"net/http"
)
// 自定义错误类型
type ApiError struct {
Code int // 错误码
Message string // 错误信息
}
// 实现error接口
func (e *ApiError) Error() string {
return e.Message
}
// 统一响应结构
type ApiResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
// 统一错误响应方法
func WriteError(w http.ResponseWriter, err *ApiError) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(err.Code)
json.NewEncoder(w).Encode(ApiResponse{
Code: err.Code,
Message: err.Message,
Data: nil,
})
}
func getUserHandler(w http.ResponseWriter, r *http.Request) {
// 模拟自定义错误
err := &ApiError{
Code: http.StatusNotFound,
Message: "用户不存在",
}
if err != nil {
WriteError(w, err)
return
}
// 正常返回
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(ApiResponse{
Code: 200,
Message: "success",
Data: "用户数据",
})
}
func main() {
http.HandleFunc("/user", getUserHandler)
http.ListenAndServe(":8080", nil)
}
使用中间件统一处理错误
如果每个接口处理函数都单独写错误判断逻辑,会有很多重复代码。可以通过中间件的方式,统一捕获接口处理过程中的错误,再统一返回响应,减少重复代码,也让错误处理逻辑更集中。
package main
import (
"encoding/json"
"net/http"
)
type ApiResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
// 错误处理中间件
func ErrorMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 使用defer捕获panic类型的错误
defer func() {
if r := recover(); r != nil {
var err error
switch x := r.(type) {
case string:
err = json.Unmarshal([]byte(x), nil)
case error:
err = x
default:
err = fmt.Errorf("未知错误")
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(ApiResponse{
Code: http.StatusInternalServerError,
Message: err.Error(),
Data: nil,
})
}
}()
next(w, r)
}
}
func getUserHandler(w http.ResponseWriter, r *http.Request) {
// 模拟触发panic的错误
panic("查询用户时发生内部错误")
}
func main() {
http.HandleFunc("/user", ErrorMiddleware(getUserHandler))
http.ListenAndServe(":8080", nil)
}
不同错误场景的处理建议
实际开发中可以根据错误类型选择不同的处理方式:
- 参数校验错误:返回400状态码,明确提示哪个参数不符合要求
- 权限错误:返回401或403状态码,提示无权限访问
- 资源不存在错误:返回404状态码,说明请求的资源不存在
- 服务端内部错误:返回500状态码,不要暴露具体内部错误细节,避免安全风险
合理的错误处理能让Web接口更健壮,也能提升前后端协作的效率,开发者可以根据项目规模选择合适的错误处理方案。