错误码

codenumberdescription
Ok0成功
Canceled1调用者取消操作
Unknown2未知错误
InvalidArgument3无效参数
DeadlineExceeded4请求超时
NotFound5未找到
AlreadyExists6已经存在
PermissionDenied7调用者没有权限
ResourceExhausted8资源已用尽
FailedPrecondition9操作被拒绝
Aborted10操作被中止
OutOfRange11尝试超出有效范围的操作
Unimplemented12服务未实现
Internal13服务内部错误
Unavailable14该服务目前不可用
DataLoss15不可恢复的数据丢失或损坏
Unauthenticated16身份未通过

异常处理

目录说明

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
Last modification:June 16th, 2022 at 10:33 pm