美文网首页
2023-03-29

2023-03-29

作者: 癞痢头 | 来源:发表于2023-04-03 14:20 被阅读0次

    protobuf go

    protoc 编译 proto文件生成go的一些说明和实验:

    protoc 生成 go 的语法:

        protoc -I=$BASE_SRC_DIR --go_out=$DST_DIR --go_opt=${options} $SUB_SRC_DIR/addressbook.proto
    

    我们有如下的项目,目录结构 和 bar.proto 文件,下文所涉及的生成测试都基于这个目录结构和文件:

    • 目录结构
    .
    ├── build.sh
    ├── out      
    ├── protos
    │   └── bar.proto
    └── readme.md
    
    
    • bar.proto
    
    syntax="proto3";
    
    option go_package="example.com/project/foo";
    
    message test {
      string id =1;
    }
    
    

    一、-I 参数

    指定定义文件proto的路径。通俗来讲就是告诉protoc从哪些文件夹下,寻找proto文件,默认从当前文件夹下找。

    实验

    
         # case1. BASE_SRC_DIR=./
              protoc -I=./ --go_out=out --go_opt=paths=import bar.proto
    
              # Could not make proto path relative: bar.proto: No such file or directory
    
         #  case2. BASE_SRC_DIR=./
              protoc -I=./ --go_out=out --go_opt=paths=import protos/bar.proto
    
         #  case3. BASE_SRC_DIR=protos
              protoc -I=./protos --go_out=out --go_opt=paths=import bar.proto
    
         #  case4. BASE_SRC_DIR=protos
              protoc -I=./protos --go_out=out --go_opt=paths=import protos/bar.proto
              
    

    其中,case1 返回找不到bar.proto 文件,case2、case3和case4 皆顺利生成。

    case2,case3能执行成功是,在protoc的执行路径下,存在文件 BASE_SRC_DIR +SUB_SRC_DIR + {filename}.proto, 即 `lsBASE_SRC_DIR + SUB_SRC_DIR +{filename}.proto` 是存在的。

    case4 中: protos/protos/bar.proto (BASE_SRC_DIR +SUB_SRC_DIR + {filename}.proto 拼接后的值) 不存在,会在当前文件夹下找 protos/bar.proto (SUB_SRC_DIR + ${filename}.proto 的值)

    注意:case4 和 case3,及case2的结果相同,但过程是不同的。

    二、 --go_out

    go_out 的参数是个文件路径,指定生成文件的输出目录,此目录需事先存在。

    go_opt 和 go import 决定的路径,在此跟路径之下。

    三、 --go_opt 选项参数

    还是以上面的文件为例: protos/bar.proto 文件,根据编译中 --go_opt的不同,生成文件的位置也不同

    • paths=import

    默认参数:指定生成文件输出路径。 默认行为是指定生成文[.pb.go]件位于 proto 定义的导出路径的后面;

    protoc -I=./ --go_out=out --go_opt=paths=import protos/bar.proto
    
    .
    ├── art.md
    ├── build.sh
    ├── out
    │   └── example.com
    │       └── project
    │           └── foo
    │               └── bar.pb.go
    ├── protos
    │   └── bar.proto
    └── readme.md
    
    • module=$PREFIX

    文件位置位于 导入路径 减去$PREFIX 的部分

    protoc -I=./ --go_out=out --go_opt=module=example.com/project protos/bar.proto
    
    .
    ├── art.md
    ├── build.sh
    ├── out
    │   └── foo
    │       └── bar.pb.go
    ├── protos
    │   └── bar.proto
    └── readme.md 
    
    • paths=source_relative

    该方式可生成和定义文件一致的目录

    protoc -I=./ --go_out=out --go_opt=paths=source_relative protos/bar.proto
    
    .
    ├── art.md
    ├── build.sh
    ├── out
    │   └── protos
    │       └── bar.pb.go
    ├── protos
    │   └── bar.proto
    └── readme.md
    

    四、. package 指定方式

    为了生成 Go 代码,必须为每个 .proto 文件提供 Go 包的导入路径(包括那些被生成的 .proto 文件传递依赖的文件)。

    指定 Go 导入路径的方式有两种:

    • 定义在 proto 文件中

      在定义proto文件时,指定go_package选项, 该选项定义包的导入路径,Go包名将是导入路径的最后一个字段,通常不建议添加。
      例如,

    
    syntax="proto3";
    
    option go_package="example.com/project/foo;package_name";
    
    
    .
    ├── art.md
    ├── build.sh
    ├── out
    │   └── example.com
    │       └── project
    │           └── foo
    │               └── bar.pb.go
    ├── protos
    │   └── bar.proto
    └── readme.md
    
    • M flag

    在 protoc 调用生成的时候,使用 M${PROTO_FILE}=${GO_IMPORT_PATH} 方式,更改指定包导入路径

    仍然使用上面的文件为例:

    protoc --proto_path=src \
      --go_opt=Mprotos/buzz.proto=example.com/project/protos/fizz \
      --go_opt=Mprotos/bar.proto=example.com/project/protos/foo \
      protos/buzz.proto protos/bar.proto
    
    

    如果两种同时指定,命令行中指定的优先级别高。

    参考文件

    相关文章

      网友评论

          本文标题:2023-03-29

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