错误码
code | number | description |
---|---|---|
Ok | 0 | 成功 |
Canceled | 1 | 调用者取消操作 |
Unknown | 2 | 未知错误 |
InvalidArgument | 3 | 无效参数 |
DeadlineExceeded | 4 | 请求超时 |
NotFound | 5 | 未找到 |
AlreadyExists | 6 | 已经存在 |
PermissionDenied | 7 | 调用者没有权限 |
ResourceExhausted | 8 | 资源已用尽 |
FailedPrecondition | 9 | 操作被拒绝 |
Aborted | 10 | 操作被中止 |
OutOfRange | 11 | 尝试超出有效范围的操作 |
Unimplemented | 12 | 服务未实现 |
Internal | 13 | 服务内部错误 |
Unavailable | 14 | 该服务目前不可用 |
DataLoss | 15 | 不可恢复的数据丢失或损坏 |
Unauthenticated | 16 | 身份未通过 |
异常处理
目录说明
demo # demo目录, 生成命令执行位置
│
├─ client # 客户端目录
│ └─ client.go
│
├─ proto # proto服务定义目录
│ ├─ user.pb.go
│ ├─ user.proto
│ └─ user_grpc.pb.go
│
├─ server # 服务目录
│ └─ server.go
生成protoc
protoc -I=./proto user.proto --go_out ./proto --go_opt paths=source_relative --go-grpc_out ./proto --go-grpc_opt=paths=source_relative user.proto
服务端
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
userPb "grpc-demo/grpc-error/proto"
"net"
)
type Server struct {
userPb.UnimplementedUserServiceServer
}
func (s Server) GetUser(ctx context.Context, request *userPb.GetUserRequest) (*userPb.GetUserResponse, error) {
return nil, status.Errorf(codes.NotFound, "not found ID: %d", request.Id)
}
func main() {
// 声明新的grpc服务GF
GRPCServer := grpc.NewServer()
// 注册用户服务
userPb.RegisterUserServiceServer(GRPCServer, &Server{})
// 监听端口
lis, err := net.Listen("tcp", "0.0.0.0:9101")
if err != nil {
panic(any(err))
}
// 启动服务
err = GRPCServer.Serve(lis)
if err != nil {
panic(any(err))
}
}
客户端
使用gRPC Status 库的 FromError 函数获取错误信息
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
userPb "grpc-demo/grpc-error/proto"
"math/rand"
"time"
)
func main() {
// 定义客户端的拦截器
var opts []grpc.DialOption // 定义选项切片
opts = append(opts, grpc.WithInsecure())
// 建立grpc连接
conn, err := grpc.Dial("127.0.0.1:9101", opts...)
if err != nil {
panic(any(err))
}
// 函数执行完后关闭连接
defer func(connect *grpc.ClientConn) {
_ = connect.Close()
}(conn)
// 实例化客户端
client := userPb.NewUserServiceClient(conn)
// 定义上下文, 设置一秒超时
ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
ctx = metadata.AppendToOutgoingContext(ctx, "name", "Gyi", "Hobby", "Eat", "Hobby", "Sleep")
// 调用函数, 使用metadata上下文
userEntity, err := client.GetUser(ctx, &userPb.GetUserRequest{
Id: int32(rand.Intn(100)),
})
if err != nil {
// 接受 grpc 错误
st, ok := status.FromError(err)
if !ok {
panic(any("获取错误失败"))
}
fmt.Printf("server error: code = %d, msg = %s\n", st.Code(), st.Message())
return
}
// 打印结果
fmt.Println(userEntity)
}
调试
# 启动服务端
go run server/server.go
# 启动客户端
go run client/client.go
# 客户端输出错误
server error: code = 5, msg = not found ID: 81
# 服务端设置超时 ; 重启服务
func (s Server) GetUser(ctx context.Context, request *userPb.GetUserRequest) (*userPb.GetUserResponse, error) {
time.Sleep(2 * time.Second)
return nil, status.Errorf(codes.NotFound, "not found ID: %d", request.Id)
}
# 客户端调用输出错误
server error: code = 4, msg = context deadline exceeded