status.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package ecode
  2. import (
  3. "fmt"
  4. "strconv"
  5. "github.com/golang/protobuf/proto"
  6. "github.com/golang/protobuf/ptypes"
  7. "go-common/library/ecode/internal/types"
  8. )
  9. // Error new status with code and message
  10. func Error(code Code, message string) *Status {
  11. return &Status{s: &types.Status{Code: int32(code.Code()), Message: message}}
  12. }
  13. // Errorf new status with code and message
  14. func Errorf(code Code, format string, args ...interface{}) *Status {
  15. return Error(code, fmt.Sprintf(format, args...))
  16. }
  17. var _ Codes = &Status{}
  18. // Status statusError is an alias of a status proto
  19. // implement ecode.Codes
  20. type Status struct {
  21. s *types.Status
  22. }
  23. // Error implement error
  24. func (s *Status) Error() string {
  25. return s.Message()
  26. }
  27. // Code return error code
  28. func (s *Status) Code() int {
  29. return int(s.s.Code)
  30. }
  31. // Message return error message for developer
  32. func (s *Status) Message() string {
  33. if s.s.Message == "" {
  34. return strconv.Itoa(int(s.s.Code))
  35. }
  36. return s.s.Message
  37. }
  38. // Details return error details
  39. func (s *Status) Details() []interface{} {
  40. if s == nil || s.s == nil {
  41. return nil
  42. }
  43. details := make([]interface{}, 0, len(s.s.Details))
  44. for _, any := range s.s.Details {
  45. detail := &ptypes.DynamicAny{}
  46. if err := ptypes.UnmarshalAny(any, detail); err != nil {
  47. details = append(details, err)
  48. continue
  49. }
  50. details = append(details, detail.Message)
  51. }
  52. return details
  53. }
  54. // WithDetails WithDetails
  55. func (s *Status) WithDetails(pbs ...proto.Message) (*Status, error) {
  56. for _, pb := range pbs {
  57. anyMsg, err := ptypes.MarshalAny(pb)
  58. if err != nil {
  59. return s, err
  60. }
  61. s.s.Details = append(s.s.Details, anyMsg)
  62. }
  63. return s, nil
  64. }
  65. // Equal for compatible.
  66. // Deprecated: please use ecode.EqualError.
  67. func (s *Status) Equal(err error) bool {
  68. return EqualError(s, err)
  69. }
  70. // Proto return origin protobuf message
  71. func (s *Status) Proto() *types.Status {
  72. return s.s
  73. }
  74. // FromCode create status from ecode
  75. func FromCode(code Code) *Status {
  76. return &Status{s: &types.Status{Code: int32(code)}}
  77. }
  78. // FromProto new status from grpc detail
  79. func FromProto(pbMsg proto.Message) Codes {
  80. if msg, ok := pbMsg.(*types.Status); ok {
  81. if msg.Message == "" {
  82. // NOTE: if message is empty convert to pure Code, will get message from config center.
  83. return Code(msg.Code)
  84. }
  85. return &Status{s: msg}
  86. }
  87. return Errorf(ServerErr, "invalid proto message get %v", pbMsg)
  88. }