美文网首页
protoc 插件开发

protoc 插件开发

作者: 周群力 | 来源:发表于2022-10-28 23:48 被阅读0次

    1. 原理

    protoc 从proto文件中抠出来结构化的数据,然后以子进程的方式启动插件,调插件、把结构化数据传给插件,让插件做生成,然后 protoc 主进程把生成的内容写进文件里
    https://www.hitzhangjie.pro/blog/2017-05-23-protoc%E5%8F%8A%E6%8F%92%E4%BB%B6%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90%E7%B2%BE%E5%8D%8E%E7%89%88

    Q: 如何告诉 protoc 用什么插件
    把插件编译好放进 path, 然后在运行 protoc 的时候带上命令行参数 –${NAME}_out, protoc 就会尝试运行该插件

    image.png
    https://rotemtam.com/2021/03/22/creating-a-protoc-plugin-to-gen-go-code/

    以 protoc-gen-go 插件为例:
    https://www.hitzhangjie.pro/blog/2017-05-23-protoc%E5%8F%8A%E6%8F%92%E4%BB%B6%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90%E7%B2%BE%E5%8D%8E%E7%89%88/#2-protoc%E6%8F%92%E4%BB%B6%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90
    生成代码的核心原理还是拼字符串。
    比如拼 enum:

    image.png

    再比如根据 service 生成 gRPC相关代码:


    image.png

    Q: gRPC 生成时,用的什么模板、传了什么struct 给模板
    A: 没用模板文件,直接用代码命令式的拼字符串

    2. protoc 插件开发示例

    比如,先生成一个 interface, 作为供开发者实现的 ”component interface“, 或者叫 "handler interface":


    image.png

    不过 component interface 里用到的 struct 还是 pb.go 里的struct,没有和 pb 解耦

    生成 server struct 和工厂函数:


    image.png

    让 server struct 实现 http api 里的每个 method,并且生成实现逻辑,即先检查字段,最后委托给 component interface


    image.png

    生成出来的 server struct 代码长这样:


    image.png
    image.png

    检查字段的逻辑,其实是靠 proto 里的 option 声明,然后在代码里做计算、得到关键 flag,最后模板渲染时根据 flag 渲染字段检查逻辑:


    image.png

    3. 如何开发生成 go 代码的插件

    最好基于一些开发框架来写插件,写起来更方便

    3.1. 基于 protogen 开发

    protogen 是官方提供的一个 go 开发框架
    https://rotemtam.com/2021/03/22/creating-a-protoc-plugin-to-gen-go-code/

    如果每次调试都需要编译一下会特别麻烦,也无法使用debug等工具


    image.png

    或者通过--descriptor_set_out 参数把整体结构打印到标准输出
    protoc 工具插件和生态 - 白云辉 - 博客园 (cnblogs.com)
    https://stackoverflow.com/questions/37730781/how-can-i-get-an-internal-representation-out-of-protoc
    https://stackoverflow.com/questions/39171581/proto-descriptor-from-proto-schema-file-or-string

    • 怎么把 message 转成 struct 结构
      protogen 没提供获取 go struct 的接口。protoc-gen-go 是自己写的 if else


      image.png

      准备自己写个 helper 库

    3.2. 基于 protoc-gen-gotemplate

    moul/protoc-gen-gotemplate: generic protocol generator based on golang's text/template (grpc/protobuf) (github.com)
    看着不错,但:

    • 缺少文档,你不知道字段有哪些
    • 没法像js 一样,用代码做model处理,必须用模板引擎语法做处理

    Idea:

    • 允许代码做model处理,比如每个 template 有个同名的 go文件,类似 html 有对应的 js
    • 允许用html和前端框架做渲染

    相关文章

      网友评论

          本文标题:protoc 插件开发

          本文链接:https://www.haomeiwen.com/subject/qrzqnrtx.html