栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

4、protobuf进阶

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

4、protobuf进阶

目录
  • 一、proto的类型
  • 二、option go_package
  • 三、proto文件import另外一个文件的message
  • 四、message嵌套
  • 五、enum使用
  • 六、map使用
  • 七、proto的内置timestamp

  • protobuf官方文档参考:http://developers.google.com/protocol-buffers/docs/proto3

一、proto的类型
  • proto的默认数值类型:当一个消息被解析的时候,如果被编码的信息不包含一个特定的singular元素,被解析的对象锁对应的域被设置为一个默认值,对于不同类型指定如下
    • 对于strings,默认值是一个空string
    • 对于bytes,默认值是一个空的bytes
    • 对于bools,默认值是false
    • 对于数值类型,默认是0
    • 对于枚举,默认是第一个定义的枚举值,必须为0


二、option go_package
  • 我们之前在stream.proto中配置的包路径为:option go_package = ".;proto";,这时候生成的proto文件路径是跟stream.proto同级目录下

    • 对应的生成命令是:protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative *.proto
  • 这时候思考,如果我们希望将pb.go生成到其他路径:

    • 修改option go_package配置:option go_package = "common/stream/proto/v1";
    • 生成命令:注意这时候不应该再使用source_relative,而应该使用import,如protoc --go_out=. --go_opt=paths=import --go-grpc_out=. --go-grpc_opt=paths=import *.proto
  • 如果我们希望生成到根目录的其他路径

    • 修改option go_package配置:option go_package = "../../common/stream/proto/v1";
    • 生成命令:注意这时候不应该再使用source_relative,而应该使用import,如protoc --go_out=. --go_opt=paths=import --go-grpc_out=. --go-grpc_opt=paths=import *.proto

三、proto文件import另外一个文件的message
  • hello.proto
syntax = "proto3";
import "base.proto";
option go_package = ".;proto";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
  rpc Ping(Empty) returns (Pong);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}
  • base.proto:比较公用的message
syntax = "proto3";

message Empty{

}

message Pong{

}
  • 实际上谷歌已经自定义了Empty:而且还包含很多其他的内置message
  • 修改后的proto:注意需要在golang中修改导入的位置,如图
//hello.proto
syntax = "proto3";
import "base.proto";
import "google/protobuf/empty.proto";
option go_package = ".;proto";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
  rpc Ping(google.protobuf.Empty) returns (Pong);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

//base.proto
syntax = "proto3";

message Pong{

}


四、message嵌套
  • message嵌套
message HelloReply {
    string message = 1;

    message Result {
        string name = 1;
        string url = 2;
    }

    repeated Result data = 2;
}
  • 嵌套后生成的pb.go代码是:HelloReply_Result
type HelloReply_Result struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
	Url  string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"`
}

五、enum使用
  • hello.proto
message HelloRequest {
  string name = 1;
  string url = 2;
  Gender g = 3;
}

enum Gender{
  MALE = 0;
  FEMALE = 1;
}
  • hello.pb.go
type Gender int32

const (
	Gender_MALE   Gender = 0
	Gender_FEMALE Gender = 1
)
  • client.go
	c := proto.NewGreeterClient(conn)
	r, err := c.SayHello(context.Background(), &proto.HelloRequest{
		Name: "test",
		Url:  "hel.com",
		G:    proto.Gender_FEMALE,
	})

六、map使用
  • hello.proto
message HelloRequest {
  string name = 1;
  string url = 2;
  Gender g = 3;
  map mp = 4;
}
  • hello.pb.go
type HelloRequest struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Name string            `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
	Url  string            `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"`
	G    Gender            `protobuf:"varint,3,opt,name=g,proto3,enum=Gender" json:"g,omitempty"`
	Mp   map[string]string `protobuf:"bytes,4,rep,name=mp,proto3" json:"mp,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}
  • client.go
	c := proto.NewGreeterClient(conn)
	r, err := c.SayHello(context.Background(), &proto.HelloRequest{
		Name: "test",
		Url:  "hel.com",
		G:    proto.Gender_FEMALE,
		Mp: map[string]string{
			"name":    "test",
			"company": "my",
		},
	})

七、proto的内置timestamp
  • timestamp的import:import "google/protobuf/timestamp.proto";
  • hello.proto的定义:内置类型都需要google.protobuf开头
syntax = "proto3";
import "base.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
option go_package = ".;proto";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
  rpc Ping(google.protobuf.Empty) returns (Pong);
}

message HelloRequest {
  string name = 1;
  string url = 2;
  Gender g = 3;
  map mp = 4;
  google.protobuf.Timestamp addTime = 5;
}

enum Gender{
  MALE = 0;
  FEMALE = 1;
}

message HelloReply {
  string message = 1;

  message Result {
    string name = 1;
    string url = 2;
  }

  repeated Result data = 2;
}
  • hello.pb.go:可以看到AddTime的类型是*timestamppb.Timestamp,点击后查看import就是client.go需要import的包名timestamppb "google.golang.org/protobuf/types/known/timestamppb"
type HelloRequest struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Name    string                 `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
	Url     string                 `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"`
	G       Gender                 `protobuf:"varint,3,opt,name=g,proto3,enum=Gender" json:"g,omitempty"`
	Mp      map[string]string      `protobuf:"bytes,4,rep,name=mp,proto3" json:"mp,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
	AddTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=addTime,proto3" json:"addTime,omitempty"`
}
  • client.go
package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/protobuf/types/known/timestamppb"
	"time"

	"MyTestProject/grpc_test/proto"
)

func main() {
	//stream
	conn, err := grpc.Dial("127.0.0.1:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer conn.Close()

	c := proto.NewGreeterClient(conn)
	r, err := c.SayHello(context.Background(), &proto.HelloRequest{
		Name: "test",
		Url:  "hel.com",
		G:    proto.Gender_FEMALE,
		Mp: map[string]string{
			"name":    "test",
			"company": "my",
		},
		AddTime: timestamppb.New(time.Now()),
	})
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	fmt.Println(r.Message)
}


暑期编程PK赛 得CSDN机械键盘等精美礼品!
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1017352.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号