Errors

You can define errors in protos and generate enums with protoc-gen-go.

Error in errors pacakge implements GRPCStatus() interface,The conversion between grpc and HTTP error code is realized, and the business reason is returned through errorinfo.

  1. {
  2. // The error code is consistent with HTTP status and can be converted into grpc status in grpc.
  3. "code": 500,
  4. // The error reason is defined as the business judgment error code.
  5. "reason": "USER_NOT_FOUND",
  6. // Error information is user-readable information and can be used as user prompt content.
  7. "message": "invalid argument error",
  8. // Error meta information, add additional extensible information for the error.
  9. "metadata": {
  10. "foo": "bar"
  11. }
  12. }

Installation

  1. go install github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2

Error Defination

api/helloworld/v1/helloworld.proto

  1. syntax = "proto3";
  2. package api.kratos.v1;
  3. import "errors/errors.proto";
  4. // Define the package name for source code reference.
  5. option go_package = "kratos/api/helloworld;helloworld";
  6. option java_multiple_files = true;
  7. option java_package = "api.helloworld";
  8. enum ErrorReason {
  9. // Set default error code.
  10. option (errors.default_code) = 500;
  11. // Set the error code separately for an enumeration.
  12. USER_NOT_FOUND = 0 [(errors.code) = 404];
  13. CONTENT_MISSING = 1 [(errors.code) = 400];
  14. }

Error Generation

To generate code with protoc.

  1. protoc --proto_path=. \
  2. --proto_path=./third_party \
  3. --go_out=paths=source_relative:. \
  4. --go-errors_out=paths=source_relative:. \
  5. $(API_PROTO_FILES)

Or use the makefile directive at the root of the project

  1. make errors

After successful execution, will be generated in the api/helloworld directory a go file,The code is as follows.

  1. package helloworld
  2. import (
  3. fmt "fmt"
  4. errors "github.com/go-kratos/kratos/v2/errors"
  5. )
  6. // This is a compile-time assertion to ensure that this generated file
  7. // is compatible with the kratos package it is being compiled against.
  8. const _ = errors.SupportPackageIsVersion1
  9. func IsUserNotFound(err error) bool {
  10. if err == nil {
  11. return false
  12. }
  13. e := errors.FromError(err)
  14. return e.Reason == ErrorReason_USER_NOT_FOUND.String() && e.Code == 404
  15. }
  16. func ErrorUserNotFound(format string, args ...interface{}) *errors.Error {
  17. return errors.New(404, ErrorReason_USER_NOT_FOUND.String(), fmt.Sprintf(format, args...))
  18. }
  19. func IsContentMissing(err error) bool {
  20. if err == nil {
  21. return false
  22. }
  23. e := errors.FromError(err)
  24. return e.Reason == ErrorReason_CONTENT_MISSING.String() && e.Code == 400
  25. }
  26. func ErrorContentMissing(format string, args ...interface{}) *errors.Error {
  27. return errors.New(400, ErrorReason_CONTENT_MISSING.String(), fmt.Sprintf(format, args...))
  28. }

Usage

  1. import "kratos/api/helloworld"
  2. err := wrong()
  3. if errors.Is(err,errors.BadRequest("USER_NAME_EMPTY","")) {
  4. // do something
  5. }
  6. e := errors.FromError(err)
  7. if e.Reason == "USER_NAME_EMPTY" && e.Code == 500 {
  8. // do something
  9. }
  10. if helloworld.IsUserNotFound(err) {
  11. // do something
  12. })