安装
下载
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/protobuf-all-3.14.0.tar.gz
tar -zxvf protobuf-all-3.14.0.tar.gz
cd protobuf-3.14.0/
./configure
make
make install
安装protoc-gen-go-grpc插件
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
问题:
protoc: error while loading shared libraries: libprotoc.so.25: cannot open shared object file: No such file or directory
两种解决方法:
- export LD_LIBRARY_PATH=/usr/local/lib
- ldconfig
为什么要执行ldconfig
我们通过控制台输出的信息可以知道,Protocol Buffers Libraries的默认安装路径在/usr/local/lib
Libraries have been installed in:
/usr/local/lib
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution - add LIBDIR to the `LD_RUN_PATH' environment variable
during linking - use the `-Wl,-rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to `/etc/ld.so.conf'
See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
而我们安装了一个新的动态链接库,ldconfig一般在系统启动时运行,所以现在会找不到这个lib,因此我们要手动执行ldconfig,让动态链接库为系统所共享,它是一个动态链接库管理命令,这就是ldconfig命令的作用
使用
protoc --go_out=../service --go_opt paths=source_relative \
--go-grpc_out=../service --go-grpc_opt paths=source_relative \
User.proto
语法速学
repeated 切片类型
syntax="proto3";
package service;
option go_package = "gaodongfei.com/service";
import "google/api/annotations.proto";
message ProdResponse{
int32 prod_stock=1;
}
message QuerySize{
int32 size=1;
}
message ProdResponseList{
repeated ProdResponse prodres=1;
}
service ProdService{
rpc GetProdStockList(QuerySize)returns(ProdResponseList){}
}
生成
type ProdResponseList struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Prodres []*ProdResponse `protobuf:"bytes,1,rep,name=prodres,proto3" json:"prodres,omitempty"`
}
enum 枚举类型
enum ProdAreas{
A=0;
B=1;
C=2;
}
message ProdRequest{
int32 prod_id=1;
ProdAreas prod_area=2;
}
生成:
ProdAreas
ProdRequest
导入外部proto
Model.proto
syntax="proto3";
package service;
option go_package = "gaodongfei.com/service";
message ProdModel{
int32 prod_id=1;
string prod_name=2;
float prod_price=3;
}
Prod.proto
如果两文件 go package 相同则直接使用 ProdModel
import "Model.proto";
生成命令
protoc --go_out=plugins=grpc:../service \
--go_opt paths=source_relative \
*.proto
日期类型
Model.proto
import "google/protobuf/timestamp.proto";
message OrderMain{
int32 order_id=1;
string order_no=2;
int32 user_id=3;
float order_money=4;
google.protobuf.Timestamp order_time=5;
}
赋值
import (
"github.com/golang/protobuf/ptypes/timestamp"
"time"
) OrderMain{OrderId:1,OrderTime:×tamp.Timestamp{Seconds:time.Now().Unix()}}
Oneof
如果你有一组字段,同时最多允许这一组中的一个字段出现,就可以使用Oneof定义这一组字段,这有点Union的意思,但是Oneof允许你设置零各值。
因为proto3没有办法区分正常的值是否是设置了还是取得缺省值(比如int64类型字段,如果它的值是0,你无法判断数据是否包含这个字段,因为0几可能是数据中设置的值,也可能是这个字段的零值),所以你可以通过Oneof取得这个功能,因为Oneof有判断字段是否设置的功能。
syntax = "proto3";
package abc;
message OneofMessage {
oneof test_oneof {
string name = 4;
int64 value = 9;
}
}
map
map类型需要设置键和值的类型,格式是"map" "<" keyType "," type ">" mapName "=" fieldNumber [ "[" fieldOptions "]"
。
message OneofMessage {
oneof test_oneof {
string name = 4;
int64 value = 9;
}
map<int64,string> field1 = 1;
}