grpc tutorial 教學

GoLang - grpc 使用 Repeated 回傳多筆數據

在設計 grpc 時,如果我們需要取得商品列表,該如何獲得?

本篇預設讀者對於 grpc 有一定的瞭解,以下將簡單舉例,先說明查單一商品,以及修改為回傳多商品,最後則是 server 與 client 端如何處理這部分的流程:

查詢單一商品

首先,在 proto 設計一個取得產品的 proto 如下:

//single product response
message ProdRequest {
  int32 prod_id = 1;//product ID
}
message ProdResponse {
  int32 prod_stock=1;//product stock
}

//product
service ProdService {
  //get product
  rpc GetProdStock (ProdRequest) returns (ProdResponse);
}

增加查詢多商品

我們新增 GetProducts service,並且 QuerySize 接收產品的尺寸 size ,ProductListResponse 則用來返回多個商品。

在這裡,我們先不填寫 ProductListResponse 內容,proto 設計如下:

//single product response
message ProdResponse {
  int32 prod_stock=1;//product stock
}


//query size
message QuerySize {
  int32 size=1;
}

//repeated prodResponse
message ProductListResponse {
  repeated ProdResponse prodres=1;
}

//product
service ProdService {

  //get product list
  rpc GetProducts(QuerySize) returns (ProductListResponse));
  
  
  //get product
  rpc GetProdStock (ProdRequest) returns (ProdResponse);
}

Repeated 修飾符

透過 reqeated 可以將返回的內容重複多次,在 go 語言就會將這個當作一個 slice 切片(其他語言就會當作 Array)

這裏, ProductListResponse 用 repeated 來定義 ProdResponse 為回傳,到時就可以返回多個 ProdResponse:

//single product response
message ProdResponse {
  int32 prod_stock=1;//product stock
}


//query size
message QuerySize {
  int32 size=1;
}

//repeated prodResponse
message ProductListResponse {
  repeated ProdResponse prodres=1;
}

//product
service ProdService {

  //get product list
  rpc GetProducts(QuerySize) returns (ProductListResponse));
  
  
  //get product
  rpc GetProdStock (ProdRequest) returns (ProdResponse);
}

接著,執行編譯 proto,例如:

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

在輸出的 pb.go 可以看到返回的 ProductListResponse 裡面的 ProdResponse 是一個 slice

//repeated prodResponse
type ProductListResponse struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Prodres []*ProdResponse `protobuf:"bytes,1,rep,name=prodres,proto3" json:"prodres,omitempty"`
}

我們在 pb.go 同層新增 ProdServices.go ,在新增 product list 時,先手動預設返回一些商品列表:

type ProdService struct {
}

//get product list
func (this *ProdService) GetProducts(context.Context, *QuerySize) (*ProductListResponse, error) {
	Products:= []*ProdResponse{
		&ProdResponse{ProdStock: 1},
		&ProdResponse{ProdStock: 2},
		&ProdResponse{ProdStock: 3},
		&ProdResponse{ProdStock: 4},
	}
	return &ProductListResponse{
		Prodres: Products,
	}, nil
}

//get product
func(this *ProdService) GetProdStock(context.Context, *ProdRequest) (*ProdResponse, error){
	return &ProdResponse{ProdStock: 1234}, nil
}

Client 端接收多筆產品數據

在 grpc client 接收多筆產品數據,

func main() {
	...
  
	//ProdService Client conn service
	prodClient:=services.NewProdServiceClient(conn)


	//prodClient.GetProducts
	prodListRes, err := prodClient.GetProducts(context.Background(),
		&services.QuerySize{Size: 10})
	if err != nil{
		log.Fatal(err)
	}
	fmt.Println(prodListRes.Prodres)

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

運行後,得到以下輸出就表示成功獲取到多筆商品列表

[prod_stock:1 prod_stock:2 prod_stock:3 prod_stock:4]

也可改成取得其中一筆

fmt.Println(prodListRes.Prodres[0].ProdStock)