package apperr import ( "errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) // Error 表示网关内部统一业务错误。 type Error struct { Status int Code string Message string } func (e *Error) Error() string { return e.Message } // New 构造一个统一错误,便于 HTTP 层直接映射。 func New(status int, code string, message string) *Error { return &Error{ Status: status, Code: code, Message: message, } } // Resolve 将任意错误转换成统一 HTTP 状态码和错误码。 func Resolve(err error) (statusCode int, code string, message string) { if err == nil { return 200, "ok", "ok" } var appErr *Error if errors.As(err, &appErr) { return appErr.Status, appErr.Code, appErr.Message } grpcStatus, ok := status.FromError(err) if !ok { return 500, "internal_error", "internal server error" } switch grpcStatus.Code() { case codes.InvalidArgument: return 400, "bad_request", grpcStatus.Message() case codes.Unauthenticated, codes.PermissionDenied: return 401, "unauthorized", grpcStatus.Message() case codes.NotFound: return 404, "not_found", grpcStatus.Message() case codes.DeadlineExceeded: return 504, "upstream_timeout", "upstream request timeout" default: return 502, "upstream_error", grpcStatus.Message() } }