自定义 golang protobuf plugin

** 看 Go高级编程 书籍, 照着里面的例子编写自定义 golang 的 protobuf plugin 失败报错 : WARNING: Package "github.com/golang/protobuf/protoc-gen-go/generator" is deprecated. A future release of golang/protobuf will delete this package, which has long been excluded from the compatibility promise.**

出现这样的问题是 github.com/golang/protobuf/protoc-gen-go/generator 这个包不允许你 init(引入), 可能是将要废弃了吧

但是看 micro 框架, 也实现了自定义protobuf插件, mirco 框架自己又重写了 generator 包,把这个包取出来代替 github.com/golang/protobuf/protoc-gen-go/generator 这个包,就可以了

让我们亲自实现自定义插件吧
  • 首先写一个插件
package netrpc

import (
	"github.com/golang/protobuf/protoc-gen-go/descriptor"  // 要安装  github.com/golang/protobuf 这个包 
	"protobuf-plugin/generator"  // 这个包是从 micro 框架拷贝过来的 下文会把 github 地址贴过来
)
// 这里要实现 generator 包里的 Plugin 接口
type netrpcPlugin struct {
	*generator.Generator
}

func (p *netrpcPlugin) Name() string {
	return "netrpc"
}

func (p *netrpcPlugin) Init(g *generator.Generator) {
	p.Generator = g
}

func (p *netrpcPlugin) GenerateImports(file *generator.FileDescriptor, imports map[generator.GoImportPath]generator.GoPackageName) {
	if len(file.Service) > 0 {
		p.genImportCode(file)
	}
}

func (p *netrpcPlugin) Generate(file *generator.FileDescriptor) {
	for _, svc := range file.Service {
		p.genServiceCode(svc)
	}
}

func (p *netrpcPlugin) genImportCode(file *generator.FileDescriptor) {
	p.P("//TODO: import code")
}

func (p *netrpcPlugin) genServiceCode(svc *descriptor.ServiceDescriptorProto) {
	p.P("//TODO : service code, name = " + svc.GetName())
}
// 注册
func init() {
	generator.RegisterPlugin(new(netrpcPlugin))
}

写 main 包 让程序跑起来 忘了说了 这个也是用的 micro 框架里的,原谅我
package main

import (
	"io/ioutil"
	"os"

	"github.com/golang/protobuf/proto"
	"protobuf-plugin/generator"
	_ "protobuf-plugin/netrpc"
)

func main() {
	g := generator.New()

	data, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		g.Error(err, "reading input")
	}

	if err := proto.Unmarshal(data, g.Request); err != nil {
		g.Error(err, "parsing input proto")
	}

	if len(g.Request.FileToGenerate) == 0 {
		g.Fail("no files to generate")
	}

	g.CommandLineParameters(g.Request.GetParameter())
	g.WrapTypes()
	g.SetPackageNames()
	g.BuildTypeNameMap()
	g.GenerateAllFiles()
	data, err = proto.Marshal(g.Response)
	if err != nil {
		g.Error(err, "failed to marshal output proto")
	}
	_, err = os.Stdout.Write(data)
	if err != nil {
		g.Error(err, "failed to write output proto")
	}
}

这样 build 或 install 安装下就行了 比如我让它生成的可执行文件的名字是 protoc-gen-go-netrpc, 开头必须是 protoc-gen-,插件必须在PATH 环境变量里, protobuf 的 protoc 编译器是通过插件机制实现对不同语言的支持。比如 protoc 命令出现 --xxx_out 格式的参数, 那么 protoc 将首先查询是否有内置的 xxx 插件, 如果没有
内置的 xxx 插件那么将继续查询当前系统中是否存在 protoc-gen-xxx 命名的可执行程序, 最终通过查询到的插件生成代码。

让我们运行命令
protoc --go-netrpc_out=plugins=netrpc:. hello.proto

这样就能解析成功 hello.proto 文件了

文件github地址

你可能感兴趣的:(golang,golang,protobuf)