编译protoc方法名称被自动大写

前言

我在使用proto时,定义了一个k8s xx方法,这个方法名称原本是小写,编译出来后,再pb文件中却是大写!

导致实现接口时,你会发现IDEA提示你 确实 实现了该接口。但是,实际上你用HTTP去访问这个接口,它就会报错,告诉你rpc方法不存在。

正文

proto文件定义如下:

syntax = "proto3";

package test;

option go_package = "./test";


import "google/api/annotations.proto";
import "protoc-gen-swagger/options/annotations.proto";
import "validate/validate.proto";



service Test{
  rpc GetK8sPod(RequestPod) returns(ResponsePod){
    option (google.api.http) = {
      get: "/getPod"
    };
    option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = {
      description : "根据条件查询pod,并返回查询结果"
      summary : "查询pod"
    };
  }
}

message RequestPod{

  option (grpc.gateway.protoc_gen_swagger.options.openapiv2_schema) = {
    json_schema : {
      title : "RequestPod"
      description : "查询pod请求"
      required: [
      ]
    }
  };

  string name = 1[(grpc.gateway.protoc_gen_swagger.options.openapiv2_field) = {
    title: "name",
    description: "名字"
  }];

  string namespace = 2[(grpc.gateway.protoc_gen_swagger.options.openapiv2_field) = {
    title: "namespace",
    description: "名空间"
  }];

}

message ResponsePod{

  option (grpc.gateway.protoc_gen_swagger.options.openapiv2_schema) = {
    json_schema : {
      title : "ResponsePod"
      description : "返回pod查询结果"
      required: [
      ]
    }
  };

  string data = 1[(grpc.gateway.protoc_gen_swagger.options.openapiv2_field) = {
    title: "data",
    description: "数据"
  }];

}





可以看到接口名称是“GetK8sPod” ,请注意此时的”k8s“的“s”是小写,当你编译后,生成出来的pb文件中,接口的名称却是大写的”K8S“,如下:

// Code generated by protoc-gen-micro. DO NOT EDIT.
// source: test.proto

package proto

import (
	fmt "fmt"
	_ "github.com/envoyproxy/protoc-gen-validate/validate"
	_ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger/options"
	_ "google.golang.org/genproto/googleapis/api/annotations"
	proto "google.golang.org/protobuf/proto"
	math "math"
)

import (
	context "context"
	api "go-micro.dev/v4/api"
	client "go-micro.dev/v4/client"
	server "go-micro.dev/v4/server"
)

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

// Reference imports to suppress errors if they are not otherwise used.
var _ api.Endpoint
var _ context.Context
var _ client.Option
var _ server.Option

// Api Endpoints for Test service

func NewTestEndpoints() []*api.Endpoint {
	return []*api.Endpoint{
		{
			Name:    "Test.GetK8sPod",
			Path:    []string{"/getPod"},
			Method:  []string{"GET"},
			Handler: "rpc",
		},
	}
}

// Client API for Test service

type TestService interface {
	GetK8SPod(ctx context.Context, in *RequestPod, opts ...client.CallOption) (*ResponsePod, error)
}

type testService struct {
	c    client.Client
	name string
}

func NewTestService(name string, c client.Client) TestService {
	return &testService{
		c:    c,
		name: name,
	}
}

func (c *testService) GetK8SPod(ctx context.Context, in *RequestPod, opts ...client.CallOption) (*ResponsePod, error) {
	req := c.c.NewRequest(c.name, "Test.GetK8sPod", in)
	out := new(ResponsePod)
	err := c.c.Call(ctx, req, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// Server API for Test service

type TestHandler interface {
	GetK8SPod(context.Context, *RequestPod, *ResponsePod) error
}

func RegisterTestHandler(s server.Server, hdlr TestHandler, opts ...server.HandlerOption) error {
	type test interface {
		GetK8SPod(ctx context.Context, in *RequestPod, out *ResponsePod) error
	}
	type Test struct {
		test
	}
	h := &testHandler{hdlr}
	opts = append(opts, api.WithEndpoint(&api.Endpoint{
		Name:    "Test.GetK8sPod",
		Path:    []string{"/getPod"},
		Method:  []string{"GET"},
		Handler: "rpc",
	}))
	return s.Handle(s.NewHandler(&Test{h}, opts...))
}

type testHandler struct {
	TestHandler
}

func (h *testHandler) GetK8SPod(ctx context.Context, in *RequestPod, out *ResponsePod) error {
	return h.TestHandler.GetK8SPod(ctx, in, out)
}

我们可以看到“TestHandler”中的接口名称为“GetK8SPod”,这个“S”神奇的变为了大写的。所以,在编译proto文件时,可能某一些单词会被编译成大写的,大家在写接口的时候,多多防范一下,免得被坑。

接着,我们实现一下“TestHandler”中的所有接口,并写一个main实例,使用postman测试一下"/getPod"接口,看看是不是与上述 结论一致。

实现handler,代码如下:

package handler

import (
	pb "test/proto"
	"context"
)

type test struct {
}

func New() *test {
	return new(test)
}

func (t *test) GetK8SPod(ctx context.Context, req *pb.RequestPod, rsp *pb.ResponsePod) error {
	rsp.Data = "hello"
	return nil
}

main.go,代码如下:

package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"net/http"
	"time"

	"test/handler"
	pb "test/proto"
	grpccli "github.com/go-micro/plugins/v4/client/grpc"
	grpcsvr "github.com/go-micro/plugins/v4/server/grpc"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"github.com/pkg/errors"
	"go-micro.dev/v4"
	"google.golang.org/grpc"
)

func program1() {
	svr := micro.NewService(
		micro.Server(
			grpcsvr.NewServer(),
		),
		micro.Client(
			grpccli.NewClient(),
		),
		micro.Name("test"),
		micro.Version("latest"),
		micro.Address(net.JoinHostPort("127.0.0.1", "8081")),
	)

	if err := pb.RegisterTestHandler(svr.Server(), handler.New()); err != nil {
		return
	}

	grpcDialOpts := []grpc.DialOption{grpc.WithInsecure()}
	grpcMux := runtime.NewServeMux(runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{}))

	if err := pb.RegisterTestGwFromEndpoint(context.Background(), grpcMux,
		net.JoinHostPort("127.0.0.1", "8081"), grpcDialOpts); err != nil {
		log.Fatalln(errors.Wrapf(err, "register http gateway failed"))
	}

	httpServer := &http.Server{
		Handler: grpcMux,
		Addr:    net.JoinHostPort("127.0.0.1", "8080"),
	}

	errStop := make(chan error, 1)

	go func() {

		errStop <- httpServer.ListenAndServe()

	}()

	go func() {

		errStop <- svr.Run()

	}()

	for {
		select {
		case err := <-errStop:
			log.Fatalln(err)
		default:
			time.Sleep(time.Millisecond * 50)
		}
	}

}

func main() {
	program1()
}

 postman,访问结果如下:

编译protoc方法名称被自动大写_第1张图片

到这里就印证了上述结论。 

如何能让"Test.GetK8sPod"接口被成功访问,目前只有一种方法,就是修改proto文件,把"GetK8sPod",改成“GetK8SPod”,就是“S”大写。如下:

syntax = "proto3";

package test;

option go_package = "./test";


import "google/api/annotations.proto";
import "protoc-gen-swagger/options/annotations.proto";
import "validate/validate.proto";



service Test{
  // K8S 全部大写
  rpc GetK8SPod(RequestPod) returns(ResponsePod){
    option (google.api.http) = {
      get: "/getPod"
    };
    option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = {
      description : "根据条件查询pod,并返回查询结果"
      summary : "查询pod"
    };
  }
}

message RequestPod{

  option (grpc.gateway.protoc_gen_swagger.options.openapiv2_schema) = {
    json_schema : {
      title : "RequestPod"
      description : "查询pod请求"
      required: [
      ]
    }
  };

  string name = 1[(grpc.gateway.protoc_gen_swagger.options.openapiv2_field) = {
    title: "name",
    description: "名字"
  }];

  string namespace = 2[(grpc.gateway.protoc_gen_swagger.options.openapiv2_field) = {
    title: "namespace",
    description: "名空间"
  }];

}

message ResponsePod{

  option (grpc.gateway.protoc_gen_swagger.options.openapiv2_schema) = {
    json_schema : {
      title : "ResponsePod"
      description : "返回pod查询结果"
      required: [
      ]
    }
  };

  string data = 1[(grpc.gateway.protoc_gen_swagger.options.openapiv2_field) = {
    title: "data",
    description: "数据"
  }];

}





再重新编译一下proto文件,并重新运行main.go,使用postman访问“/getPod”接口,结果如下:

编译protoc方法名称被自动大写_第2张图片

你可能感兴趣的:(Golang,protoc)