如何使用 grpc 方法处理程序解决此问题

How to fix this issue with grpc method handler

我是 golang 的新手,想尝试使用 grpc 代码来更好地理解它。为此,我按照此处显示的示例进行操作:

https://devicharan.wordpress.com/

源代码在这里: https://github.com/devicharan/basicwebapp

不幸的是,当我 运行 此代码并执行 go build 时,我收到一条错误消息,内容如下:

# basicwebapp/proto
proto/CatalogService.pb.go:126: cannot use _CatalogService_GetProductCatalog_Handler (type func(interface {},   context.Context, []byte) (proto.Message, error)) as type grpc.methodHandler in field value
proto/RecommendationService.pb.go:99: cannot use _RecommendationService_GetRecommendations_Handler (type func(interface {}, context.Context, []byte) (proto.Message, error)) as type grpc.methodHandler in field value

我不知道这意味着什么,也不知道我需要更改什么才能开始找到解决方法。是代码本身有问题还是我的 Go 配置有问题?另外,有没有人可以推荐一个好的 Go 调试器?

这是 CatalogService.pb.go 的代码:

// Code generated by protoc-gen-go.
// source: CatalogService.proto
// DO NOT EDIT!

/*
Package protos is a generated protocol buffer package.

It is generated from these files:
    CatalogService.proto
    Product.proto
    RecommendationService.proto

It has these top-level messages:
    Category
    CatalogResponse
    CatalogRequest
*/
package protos

import proto "github.com/golang/protobuf/proto"

import (
    context "golang.org/x/net/context"
    grpc "google.golang.org/grpc"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal

type Category struct {
    CategoryName string `protobuf:"bytes,1,opt,name=categoryName" json:"categoryName,omitempty"`
}

func (m *Category) Reset()         { *m = Category{} }
func (m *Category) String() string { return proto.CompactTextString(m) }
func (*Category) ProtoMessage()    {}

type CatalogResponse struct {
    Products []*Product `protobuf:"bytes,1,rep,name=products" json:"products,omitempty"`
}

func (m *CatalogResponse) Reset()         { *m = CatalogResponse{} }
func (m *CatalogResponse) String() string { return proto.CompactTextString(m) }
func (*CatalogResponse) ProtoMessage()    {}

func (m *CatalogResponse) GetProducts() []*Product {
    if m != nil {
        return m.Products
    }
    return nil
}

type CatalogRequest struct {
    Category *Category `protobuf:"bytes,1,opt,name=category" json:"category,omitempty"`
}

func (m *CatalogRequest) Reset()         { *m = CatalogRequest{} }
func (m *CatalogRequest) String() string { return proto.CompactTextString(m) }
func (*CatalogRequest) ProtoMessage()    {}

func (m *CatalogRequest) GetCategory() *Category {
    if m != nil {
        return m.Category
    }
    return nil
}

func init() {
}

// Client API for CatalogService service

type CatalogServiceClient interface {
    GetProductCatalog(ctx context.Context, in *CatalogRequest, opts ...grpc.CallOption) (*CatalogResponse, error)
}

type catalogServiceClient struct {
    cc *grpc.ClientConn
}

func NewCatalogServiceClient(cc *grpc.ClientConn) CatalogServiceClient {
    return &catalogServiceClient{cc}
}

func (c *catalogServiceClient) GetProductCatalog(ctx context.Context, in *CatalogRequest, opts ...grpc.CallOption) (*CatalogResponse, error) {
    out := new(CatalogResponse)
    err := grpc.Invoke(ctx, "/protos.CatalogService/GetProductCatalog", in, out, c.cc, opts...)
    if err != nil {
        return nil, err
    }
    return out, nil
}

// Server API for CatalogService service

type CatalogServiceServer interface {
    GetProductCatalog(context.Context, *CatalogRequest) (*CatalogResponse, error)
}

func RegisterCatalogServiceServer(s *grpc.Server, srv CatalogServiceServer) {
    s.RegisterService(&_CatalogService_serviceDesc, srv)
}

func _CatalogService_GetProductCatalog_Handler(srv interface{}, ctx context.Context, buf []byte) (proto.Message, error) {
    in := new(CatalogRequest)
    if err := proto.Unmarshal(buf, in); err != nil {
        return nil, err
    }
    out, err := srv.(CatalogServiceServer).GetProductCatalog(ctx, in)
    if err != nil {
        return nil, err
    }
    return out, nil
}

var _CatalogService_serviceDesc = grpc.ServiceDesc{
    ServiceName: "protos.CatalogService",
    HandlerType: (*CatalogServiceServer)(nil),
    Methods: []grpc.MethodDesc{
        {
            MethodName: "GetProductCatalog",
            Handler:    _CatalogService_GetProductCatalog_Handler,
        },
    },
    Streams: []grpc.StreamDesc{},
}

这是RecommendationService.pg.go

// Code generated by protoc-gen-go.
// source: RecommendationService.proto
// DO NOT EDIT!

package protos

import proto "github.com/golang/protobuf/proto"

import (
    context "golang.org/x/net/context"
    grpc "google.golang.org/grpc"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal

type RecommendationResponse struct {
    Result []*RecommendationResponse_Recommendation `protobuf:"bytes,1,rep,name=result" json:"result,omitempty"`
}

func (m *RecommendationResponse) Reset()         { *m = RecommendationResponse{} }
func (m *RecommendationResponse) String() string { return proto.CompactTextString(m) }
func (*RecommendationResponse) ProtoMessage()    {}

func (m *RecommendationResponse) GetResult() []*RecommendationResponse_Recommendation {
    if m != nil {
        return m.Result
    }
    return nil
}

type RecommendationResponse_Recommendation struct {
    Rating    int32 `protobuf:"varint,1,opt,name=rating" json:"rating,omitempty"`
    Productid int32 `protobuf:"varint,2,opt,name=productid" json:"productid,omitempty"`
}

func (m *RecommendationResponse_Recommendation) Reset()         { *m = RecommendationResponse_Recommendation{} }
func (m *RecommendationResponse_Recommendation) String() string { return proto.CompactTextString(m) }
func (*RecommendationResponse_Recommendation) ProtoMessage()    {}

func init() {
}

// Client API for RecommendationService service

type RecommendationServiceClient interface {
    GetRecommendations(ctx context.Context, in *Product, opts ...grpc.CallOption) (*RecommendationResponse, error)
}

type recommendationServiceClient struct {
    cc *grpc.ClientConn
}

func NewRecommendationServiceClient(cc *grpc.ClientConn) RecommendationServiceClient {
    return &recommendationServiceClient{cc}
}

func (c *recommendationServiceClient) GetRecommendations(ctx context.Context, in *Product, opts ...grpc.CallOption) (*RecommendationResponse, error) {
    out := new(RecommendationResponse)
    err := grpc.Invoke(ctx, "/protos.RecommendationService/GetRecommendations", in, out, c.cc, opts...)
    if err != nil {
        return nil, err
    }
    return out, nil
}

// Server API for RecommendationService service

type RecommendationServiceServer interface {
    GetRecommendations(context.Context, *Product) (*RecommendationResponse, error)
}

func RegisterRecommendationServiceServer(s *grpc.Server, srv RecommendationServiceServer) {
    s.RegisterService(&_RecommendationService_serviceDesc, srv)
}

func _RecommendationService_GetRecommendations_Handler(srv interface{}, ctx context.Context, buf []byte) (proto.Message, error) {
    in := new(Product)
    if err := proto.Unmarshal(buf, in); err != nil {
        return nil, err
    }
    out, err := srv.(RecommendationServiceServer).GetRecommendations(ctx, in)
    if err != nil {
        return nil, err
    }
    return out, nil
}

var _RecommendationService_serviceDesc = grpc.ServiceDesc{
    ServiceName: "protos.RecommendationService",
    HandlerType: (*RecommendationServiceServer)(nil),
    Methods: []grpc.MethodDesc{
        {
            MethodName: "GetRecommendations",
            Handler:    _RecommendationService_GetRecommendations_Handler,
        },
    },
    Streams: []grpc.StreamDesc{},
}

对于任何 运行 遇到同样问题的人,我所做的只是改变我构建原型文件的方式。博客页面上有一条评论突出显示了一些缺失的步骤,我遵循它并执行了以下 protoc 命令以从 proto 文件生成代码:

protoc --go_out=plugins=grpc:. *.proto

我 运行 在包含我的原型文件的目录中执行此命令,然后在我的 main.go 文件上执行了 go 构建,现在一切正常。

基本上你的protoc-gen-go和grpc的版本不匹配。所以将它们同步到最新版本并重新安装 protoc-gen-go 将解决问题:

go get -u github.com/golang/protobuf/
cd github.com/golang/protobuf/
make

go get -u github.com/grpc/grpc-go

我遇到了同样的问题,正在重新安装或新命令似乎不起作用。

但是:如果您更改

codec grpc.Codec, buf []byte

在处理程序定义中变成:

dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor

codec.Unmarshal(buf, in) 

进入

dec(in)

(全部在您的 .pb.go 文件中的处理程序定义中)

似乎有效。

更改此文件当然不是最佳选择,每次重新编译它都会覆盖您的更改,但至少有一个解决方法,直到我弄清楚我搞砸了什么。