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)