- 扩展 errors.proto,使用proto来定义“错误message”
- 完全兼容 kratos errors
go install github.com/lyouthzzz/protoc-gen-go-errors
syntax = "proto3";
package errors;
option go_package = "github.com/go-kratos/kratos/v2/errors;errors";
option java_multiple_files = true;
option java_package = "com.github.kratos.errors";
option objc_class_prefix = "KratosErrors";
import "google/protobuf/descriptor.proto";
extend google.protobuf.EnumOptions {
int32 default_code = 1108;
string default_message = 2108;
}
extend google.protobuf.EnumValueOptions {
int32 code = 1109;
string message = 2109;
}
syntax = "proto3";
package example;
import "errors/errors.proto";
option go_package = "github.com/lyouthzzz/protoc-gen-go-errors/examples";
enum ErrorReason {
// 设置缺省错误码
option (errors.default_code) = 500;
// 设置缺省错误信息
option (errors.default_message) = "未知错误";
// 参数错误
ERROR_REASON_INVALID_PARAM = 0 [(errors.code) = 400, (errors.message) = "参数错误"];
// 用户未授权
ERROR_REASON_USER_UNAUTHORIZED = 1 [(errors.code) = 401, (errors.message) = "用户未授权"];
// 用户无权限
ERROR_REASON_USER_FORBIDDEN = 2 [(errors.code) = 403, (errors.message) = "用户无权限"];
// 409 业务错误:xxx状态冲突
ERROR_REASON_STATUS_CONFLICT = 3 [(errors.code) = 409, (errors.message) = "xxx状态冲突"];
}
生成代码:make errors
protoc --proto_path=. \
--go_out=paths=source_relative:. \
--go-errors_out=paths=source_relative:. \
$(EXAMPLE_PROTO_FILES)
// Code generated by protoc-gen-go-errors. DO NOT EDIT.
package examples
import (
fmt "fmt"
errors "github.com/go-kratos/kratos/v2/errors"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the kratos package it is being compiled against.
const _ = errors.SupportPackageIsVersion1
// 参数错误
func IsErrorReasonInvalidParam(err error) bool {
if err == nil {
return false
}
e := errors.FromError(err)
return e.Reason == ErrorReason_ERROR_REASON_INVALID_PARAM.String() && e.Code == 400
}
// 参数错误
func ErrorErrorReasonInvalidParam(format string, args ...interface{}) *errors.Error {
return errors.New(400, ErrorReason_ERROR_REASON_INVALID_PARAM.String(), fmt.Sprintf(format, args...))
}
// 参数错误
func ErrorMessageErrorReasonInvalidParam() *errors.Error {
return errors.New(400, ErrorReason_ERROR_REASON_INVALID_PARAM.String(), "参数错误")
}
// 用户未授权
func IsErrorReasonUserUnauthorized(err error) bool {
if err == nil {
return false
}
e := errors.FromError(err)
return e.Reason == ErrorReason_ERROR_REASON_USER_UNAUTHORIZED.String() && e.Code == 401
}
// 用户未授权
func ErrorErrorReasonUserUnauthorized(format string, args ...interface{}) *errors.Error {
return errors.New(401, ErrorReason_ERROR_REASON_USER_UNAUTHORIZED.String(), fmt.Sprintf(format, args...))
}
// 用户未授权
func ErrorMessageErrorReasonUserUnauthorized() *errors.Error {
return errors.New(401, ErrorReason_ERROR_REASON_USER_UNAUTHORIZED.String(), "用户未授权")
}
// 用户无权限
func IsErrorReasonUserForbidden(err error) bool {
if err == nil {
return false
}
e := errors.FromError(err)
return e.Reason == ErrorReason_ERROR_REASON_USER_FORBIDDEN.String() && e.Code == 403
}
// 用户无权限
func ErrorErrorReasonUserForbidden(format string, args ...interface{}) *errors.Error {
return errors.New(403, ErrorReason_ERROR_REASON_USER_FORBIDDEN.String(), fmt.Sprintf(format, args...))
}
// 用户无权限
func ErrorMessageErrorReasonUserForbidden() *errors.Error {
return errors.New(403, ErrorReason_ERROR_REASON_USER_FORBIDDEN.String(), "用户无权限")
}
// 409 业务错误:xxx状态冲突
func IsErrorReasonStatusConflict(err error) bool {
if err == nil {
return false
}
e := errors.FromError(err)
return e.Reason == ErrorReason_ERROR_REASON_STATUS_CONFLICT.String() && e.Code == 409
}
// 409 业务错误:xxx状态冲突
func ErrorErrorReasonStatusConflict(format string, args ...interface{}) *errors.Error {
return errors.New(409, ErrorReason_ERROR_REASON_STATUS_CONFLICT.String(), fmt.Sprintf(format, args...))
}
// 409 业务错误:xxx状态冲突
func ErrorMessageErrorReasonStatusConflict() *errors.Error {
return errors.New(409, ErrorReason_ERROR_REASON_STATUS_CONFLICT.String(), "xxx状态冲突")
}
// 第一种:使用proto定义错误信息
func A() error {
return ErrorMessageErrorReasonInvalidParam()
}
// 第二种:覆盖proto错误信息(以前用法)
func B() error {
return ErrorErrorReasonInvalidParam("用户ID不能为空")
}
// 第三种:使用错误携带信息,携带根因,携带元数据
func C() error {
return ErrorMessageErrorReasonStatusConflict().
WithCause(fmt.Errorf("status has already updated")).
WithMetadata(map[string]string{"uid": "xxxxxxxxx"})
}