Proto3的import和IDE中设置

9/14/2022

本篇内容:

  • proto的package和编译后源码的package
  • import 怎么用
  • IDE中的配置

# 一、引入其他文件

项目开发中难免要引入其他已经写好的 proto 文件,或者依赖第三方的proto文件。

proto支持import指令。然而刚开始使用 proto 时,如果不清楚import的机制,使用起来会很头大。

# 1.理解proto的包

package com.project;

proto 的 package 定义了proto文件之间的逻辑关联。

proto 的 package 建议使用全路径,并且包名与目录关系一一对应。这关系到import的效果。

此外一般要在proto文件中声明目标语言的全类名或者包路径,否则当编译成Java或go语言时,package会成为Java全类名或go的包名。

如果生成的go文件路径存放不对,甚至会出现“编译通过,一访问就报错”的奇怪现象。

建议在 proto文件中声明 java_packagego_package 来制定编译后源码的包名,如:

syntax = "proto3";

package com.example.user;
option java_package = "com.example.user.grpc";
option go_package = "github.com/example/user"

其他语言的可以参考官网。

# 2.引入其他文件

在proto中,哪怕两个文件属于同一个包,引用时也需要import

可以理解为每个 proto 文件都是相互独立的。

引入其他proto的方式:

  • 通过文件路径引入文件
  • 通过包名,引用message
  • 如果在相同的包内,包名可以省略直接使用
  • 如果载相同的父包内,可以只写最后一个
  • 如果不在同一个包下,需要写完整包名
syntax = "proto3";

package com.example.user;

import "user.proto"

message MessageExample {
    //相同包内可以省略包名
    Person people = 1;
    //相同的父包只写最后一个
    order.Order order_info = 2;
    //完全不同的包名 写完整包名
    google.protobuf.Timestamp timestamp = 3;
}

这里的文件名写的是相对路径

相对的是:在执行 protoc 命令时, -I 指定的路径。

-I 是参数简写,完整参数名是--proto_path

如果在执行时添加了多个 -I 参数,那么每一个都会是寻找依赖文件的相对路径。

# 3.第三方的proto

使用较多的是 google定义的proto,比如空对象和时间戳。

syntax = "proto3";

package com.example.user;

import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";

message Temperature {
  //使用时间戳
  google.protobuf.Timestamp timestamp = 1;
}

service Backend {
    //返回空对象
    rpc GetList(Req)returns(google.protobuf.Empty);
}

编译时需要**同时指定我们的proto文件目录和google的proto目录,**假如将其下载到了/data/googleapis目录下,编译指令如下:

protoc -I . \
-I /data/googleapis \
--java_out=. user.proto

# 4.import的嵌套

假如 X import 了 Y 和 Z,而 A import了 X。

那么A只能使用 X 中定义的message,而无法使用 Y 和 Z 中定义的message。

如果想打破这种限制,需要在 X 中使用 import public。

import public "user.proto"

# 二、IDE中的设置

Idea、GoLand、VSCode 都支持 ProtoBuf 的插件。

如果 IDE 配置不正确,在编辑的时候IDE会报红,且无法进行语法提示

其实IDE校验的方式和protoc是一致的,只要指定了正确的 -I 路径就好。

Java的Idea一般是能自动配置的,如果保存,可参考GoLand的配置。

在GoLand 中配置如下: