在Golang开发中,函数返回结果和错误的方式如果不统一,会让调用方需要适配多种返回逻辑,既容易出错也增加维护成本。实现统一错误处理和返回格式封装,可以让项目代码结构更清晰,逻辑更规范。

统一返回格式的结构体定义
首先需要定义一个通用的返回结构体,包含状态码、错误信息、返回数据三个核心字段,满足大部分接口和数据返回的需求。
package response
// 通用返回结构体
type CommonResponse struct {
Code int `json:"code"` // 状态码,0表示成功,非0表示错误
Message string `json:"message"` // 错误信息,成功时为空或提示信息
Data interface{} `json:"data"` // 返回的业务数据,无数据时可以为nil
}
封装统一的成功和错误返回函数
基于通用结构体,封装两个基础函数,分别处理成功返回和错误返回的场景,后续所有业务函数都可以直接调用这两个函数返回结果。
package response
import "errors"
// 成功返回函数,传入返回数据即可
func Success(data interface{}) CommonResponse {
return CommonResponse{
Code: 0,
Message: "操作成功",
Data: data,
}
}
// 错误返回函数,传入错误码和错误信息
func Error(code int, message string) CommonResponse {
return CommonResponse{
Code: code,
Message: message,
Data: nil,
}
}
// 从error对象生成错误返回,默认错误码为500
func ErrorFromErr(err error) CommonResponse {
if err == nil {
return Success(nil)
}
return CommonResponse{
Code: 500,
Message: err.Error(),
Data: nil,
}
}
业务函数中使用统一返回格式
在实际的业务函数中,不再单独返回error和业务数据,而是直接返回封装好的CommonResponse结构体,调用方只需要解析这个结构体即可处理所有返回情况。
package service
import (
"errors"
"testproject/response"
)
// 模拟查询用户信息的业务函数
func GetUserInfo(userId int) response.CommonResponse {
// 模拟参数校验错误
if userId <= 0 {
return response.Error(1001, "用户ID参数不合法")
}
// 模拟查询数据库出错
if userId == 999 {
return response.ErrorFromErr(errors.New("数据库查询失败"))
}
// 模拟查询成功返回数据
userData := map[string]interface{}{
"user_id": userId,
"username": "测试用户",
"age": 20,
}
return response.Success(userData)
}
调用方处理返回结果
调用业务函数后,只需要判断返回结构体的Code字段即可区分成功和失败,不需要再单独处理error对象,逻辑更简单。
package main
import (
"encoding/json"
"fmt"
"testproject/service"
)
func main() {
// 测试正常情况
resp1 := service.GetUserInfo(1)
data1, _ := json.Marshal(resp1)
fmt.Println("正常返回结果:", string(data1))
// 测试参数错误情况
resp2 := service.GetUserInfo(-1)
data2, _ := json.Marshal(resp2)
fmt.Println("参数错误返回结果:", string(data2))
// 测试数据库错误情况
resp3 := service.GetUserInfo(999)
data3, _ := json.Marshal(resp3)
fmt.Println("数据库错误返回结果:", string(data3))
}
进阶:自定义错误类型和错误码管理
如果项目中的错误码较多,可以单独维护一个错误码常量文件,同时可以定义自定义错误类型,携带更多错误信息,让错误处理更灵活。
package errcode
// 错误码常量定义
const (
SuccessCode = 0
ParamErrorCode = 1001
DBErrorCode = 1002
NetworkErrorCode = 1003
)
// 错误码对应的默认错误信息
var ErrorMsgMap = map[int]string{
SuccessCode: "操作成功",
ParamErrorCode: "参数不合法",
DBErrorCode: "数据库操作失败",
NetworkErrorCode: "网络请求失败",
}
// 获取错误码对应的错误信息
func GetMsg(code int) string {
if msg, ok := ErrorMsgMap[code]; ok {
return msg
}
return "未知错误"
}
修改之前的Error函数,可以结合错误码常量使用:
package response
import "testproject/errcode"
// 结合错误码常量返回错误
func ErrorWithCode(code int) CommonResponse {
return CommonResponse{
Code: code,
Message: errcode.GetMsg(code),
Data: nil,
}
}
注意事项
- 通用返回结构体的字段标签需要根据实际使用的序列化方式调整,比如使用json序列化就加
json:"xxx"标签。 - 错误码的定义需要统一规划,避免不同模块使用相同的错误码表示不同的错误含义。
- 如果是HTTP接口场景,可以结合这个统一返回格式,在接口层统一处理响应序列化,不需要每个接口单独处理。