protobuf repeated 怎么用的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了protobuf repeated 怎么用的相关的知识,希望对你有一定的参考价值。

参考技术A protobuf repeated的数据类型和C++的Vector,list类似,只能传输相同的数据类型。 当然,如果你为了传输多种数据类型,可以使用类似与C++union的方式,用个大消息,消息的每个字段都使用optional标记,你在业务处理的时候,每次只对一个字段赋值同样可以达到目的。
另外: repeated只能表示数据有还是没有,在没有的时候,究竟是保留原有的数据不动,还是删除所有数据,这点有歧义。需要使用另外的字段进行处理。本回答被提问者和网友采纳
参考技术B protobuf repeated类型的使用
protobuf是Google开发的一个序列化框架,类似XML,JSON,基于二进制,比传统的XML表示同样一段内容要短小得多。通过protobuf,可以很轻松的调用相关方法来完成业务数据的序列化与反序列化。protobuf repeated类型相当于std的vector,可以用来存放N个相同类型的内容,文章将简单介绍protobuf repeated的使用。
首先定义一个protobuf结构,如下:

message Person
required int32 age = 1;
required string name = 2;


message Family
repeated Person person = 1;


下面以例子简单说明如何使用:

int main(int argc, char* argv[])


GOOGLE_PROTOBUF_VERIFY_VERSION;

Family family;
Person* person;

// 添加一个家庭成员,John
person = family.add_person();
person->set_age(25);
person->set_name("John");

// 添加一个家庭成员,Lucy
person = family.add_person();
person->set_age(23);
person->set_name("Lucy");

// 添加一个家庭成员,Tony
person = family.add_person();
person->set_age(2);
person->set_name("Tony");

// 显示所有家庭成员
int size = family.person_size();

cout << "这个家庭有 " << size << " 个成员,如下:" << endl;

for(int i=0; i<size; i++)

Person psn = family.person(i);
cout << i+1 << ". " << psn.name() << ", 年龄 " << psn.age() << endl;


getchar();
return 0;

grpc之protobuf常用语法速学

1,语法速学(1):返回商品”数组”、repeated修饰符

Repeated:是一个修饰符,返回字段可以重复任意多次(包括0次) 可以认为就是一个数组(切片)

 

服务端:

创建protobuf文件

syntax="proto3";
package services;
import "google/api/annotations.proto";

message  ProdRequest {
    int32 prod_id =1;   //传入的商品ID
}
message ProdResponse{
    int32 prod_stock=1;//商品库存
}

message QuerySize{
    int32 size = 1;//页尺寸
}

//返回 一堆商品库存,使用了repeated修饰符
message ProdResponseList{
    repeated ProdResponse prodres=1;
}

service ProdService {
    rpc GetProdStock (ProdRequest) returns (ProdResponse){
        option (google.api.http) = {
            get: "/v1/prod/{prod_id}"
        };

    }
    rpc GetProdStocks(QuerySize) returns (ProdResponseList){

    }
}

 

生成Prod.pb.go文件

cd pbfiles && protoc --go_out=plugins=grpc:../services  Prod.proto

 

创建ProdSerbice.go文件

package services

import (
    "context"
)

type ProdService struct {

}

func(this *ProdService) GetProdStock(ctx context.Context, request *ProdRequest) (*ProdResponse, error) {

      return &ProdResponse{ProdStock:20},nil
}

func (this *ProdService) GetProdStocks(ctx context.Context,size *QuerySize) (*ProdResponseList, error){
    var Prodres []*ProdResponse
    Prodres = make([]*ProdResponse,0,3)
    Prodres = append(Prodres,&ProdResponse{ProdStock:28,})
    Prodres = append(Prodres,&ProdResponse{ProdStock:29,})
    Prodres = append(Prodres,&ProdResponse{ProdStock:30,})
    return &ProdResponseList{
        Prodres:Prodres,
    },nil
}

 

server.go

package main

import (
    "google.golang.org/grpc"
    "grpcpro/services"
    "net"
)

func main()  {
    rpcServer:=grpc.NewServer()
    services.RegisterProdServiceServer(rpcServer,new(services.ProdService))

    lis,_:=net.Listen("tcp",":8081")

    rpcServer.Serve(lis)


}

启动服务

go run server.go

 

客户端:

拷贝服务端的生成的文件Prod.pb.go到客户端目录下

mian.go

package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "gprccli/services"
    "log"
)

func main(){

    conn,err:=grpc.Dial(":8081",grpc.WithInsecure())
    if err!=nil{
        log.Fatal(err)
    }
    defer conn.Close()

    prodClient:=services.NewProdServiceClient(conn)
    ctx:=context.Background()

    //prodRes,err:=prodClient.GetProdStock(context.Background(),
    //    &services.ProdRequest{ProdId:12})
    //if err!=nil{
    //    log.Fatal(err)
    //}
    //fmt.Println(prodRes.ProdStock)

    response,err := prodClient.GetProdStocks(ctx,&services.QuerySize{Size:10})

    if err!=nil{
        log.Fatal(err)
    }
    fmt.Println(response.Prodres[2].ProdStock)
}

启动客户端client 调用服务端gprc服务

go run main.go

 

2,语法速学(2): 使用枚举、获取分区商品库存

  1、传入一个商品ID 获取一个商品库存。

  2、根据size获取一堆商品的库存列表

  3,创建枚举类型,支持分区枚举参数

enum ProdAreas{
    A=0;
    B=1;
    C=2;
}

ProdService.go

package services

import (
    "context"
)

type ProdService struct {}

func(this *ProdService) GetProdStock(ctx context.Context, request *ProdRequest) (*ProdResponse, error) {

      var stock int32=0
      if request.ProdArea==ProdAreas_A{
          stock=30
      }else if request.ProdArea==ProdAreas_B{
          stock=31
      }else{
          stock=50
      }
      return &ProdResponse{ProdStock:stock},nil
}
func(this *ProdService) GetProdStocks(ctx context.Context,size *QuerySize) (*ProdResponseList, error)  {
            Prodres:= []*ProdResponse{
                    &ProdResponse{ProdStock:28},
                    &ProdResponse{ProdStock:29},
                    &ProdResponse{ProdStock:30},
                    &ProdResponse{ProdStock:31},
            }
            return &ProdResponseList{
                Prodres:Prodres,
            },nil
}

 

语法速学(3): 导入外部Proto、获取商品信息

 

服务端:

Models.proto

syntax="proto3";
package services;
message ProdModel{ //商品模型
    int32 prod_id=1;
    string prod_name=2;
    float prod_price=3;
}

 

Prod.proto

syntax="proto3";
package services;


import "google/api/annotations.proto";
import "Models.proto";

enum ProdAreas{
    A=0;
    B=1;
    C=2;
}

message  ProdRequest {
    int32 prod_id =1;   //传入的商品ID
}
message ProdResponse{
    int32 prod_stock=1;//商品库存
}

message QuerySize{
    int32 size = 1;//页尺寸
}

//返回 一堆商品库存,使用了repeated修饰符
message ProdResponseList{
    repeated ProdResponse prodres=1;
}

service ProdService {
    rpc GetProdStock (ProdRequest) returns (ProdResponse){
        option (google.api.http) = {
            get: "/v1/prod/{prod_id}"
        };

    }
    rpc GetProdStocks(QuerySize) returns (ProdResponseList){

    }

    rpc GetProdInfo(ProdRequest) returns(ProdModel){}
}

 

生成pb.go文件

protoc --go_out=plugins=grpc:../services  Prod.proto

protoc --go_out=plugins=grpc:../services  Models.proto

 

ProdService.go

package services

import (
    "context"
)

type ProdService struct {

}

func(this *ProdService) GetProdStock(ctx context.Context, request *ProdRequest) (*ProdResponse, error) {

      return &ProdResponse{ProdStock:20},nil
}

func (this *ProdService) GetProdStocks(ctx context.Context,size *QuerySize) (*ProdResponseList, error){
    var Prodres []*ProdResponse
    Prodres = make([]*ProdResponse,0,3)
    Prodres = append(Prodres,&ProdResponse{ProdStock:28,})
    Prodres = append(Prodres,&ProdResponse{ProdStock:29,})
    Prodres = append(Prodres,&ProdResponse{ProdStock:30,})
    return &ProdResponseList{
        Prodres:Prodres,
    },nil
}

func (this *ProdService) GetProdInfo(ctx context.Context, in *ProdRequest) (*ProdModel, error){

    ret:=ProdModel{
        ProdId:101,
        ProdName:"测试商品",
        ProdPrice:20.5,
    }
    return &ret,nil
}

 

 

客户端:

拷贝服务端 Models.pb.go和Prod.pb.go到客户端下

package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "gprccli/services"
    "log"
)

func main(){

    conn,err:=grpc.Dial(":8081",grpc.WithInsecure())
    if err!=nil{
        log.Fatal(err)
    }
    defer conn.Close()

    prodClient:=services.NewProdServiceClient(conn)
    ctx:=context.Background()

    //prodRes,err:=prodClient.GetProdStock(context.Background(),
    //    &services.ProdRequest{ProdId:12})
    //if err!=nil{
    //    log.Fatal(err)
    //}
    //fmt.Println(prodRes.ProdStock)

    //response,err := prodClient.GetProdStocks(ctx,&services.QuerySize{Size:10})
    //
    //if err!=nil{
    //    log.Fatal(err)
    //}
    //fmt.Println(response.Prodres[2].ProdStock)

    prod,err :=prodClient.GetProdInfo(ctx,&services.ProdRequest{ProdId:12})
    if err!=nil{
        log.Fatal(err)
    }
    fmt.Println(prod)
}

 

以上是关于protobuf repeated 怎么用的的主要内容,如果未能解决你的问题,请参考以下文章

修改gorm支持protobuf

lua 中protobuf repeated 嵌套类 复合类型

unity protobuf使用repeated字段转c#文件后List只读问题

protobuf 学习 收藏的文章

win32下protobuf 的使用(附带cmake的简单使用,包含复杂字段repeated)

grpc之protobuf常用语法速学