希曼日记

错误处理

  • status.New() 创建一个grpc错误, 使用.Err()来输出错误
  • status.Error() 使用一个grpc错误
  • st.WithDetails 给错误携带一个详细信息的包装, 可从"google.golang.org/genproto/googleapis/rpc/errdetails" 获取现成的错误包装 服务端示例:
"google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

if s.count[req.Name] > 1 {
			st := status.New(codes.ResourceExhausted, "请求限制")
			details, err := 
			st.WithDetails(&errdetails.QuotaFailure{
				Violations: []*errdetails.QuotaFailure_Violation{
					{
						Subject:     fmt.Sprintf("name:%v", req.Name),
						Description: "每个name只能被调用一次",
					},
				},
			})
			if err != nil { // WithDetails执行失败,返回status.Err
				return st.Err()
			}
			return details.Err()
		}

客户端示例:

  • status.Convert(err) 将普通err转成gRPC的错误 使用for来判断是哪个错误
if err != nil {
				// 客户端展示服务端使用staus.WithDetails包装的详细错误
				s := status.Convert(err)
				for _, details := range s.Details() {
					switch details.(type) {
					// 判断错误的类型, 注意需要指针
					case *errdetails.QuotaFailure:
						log.Printf("接收到QuotaFailure错误: %s \n", details)
						return
					default:
						log.Printf("接收到其他错误: %v", details)
						return
					}
				}

			}