zoukankan      html  css  js  c++  java
  • grpc-golang入门

    安装grpc相关服务

    本文以mac系统为例安装,其他操作系统请参考官网安装。

    brew install protobuf
    brew install protoc-gen-go
    brew install protoc-gen-go-grpc
    
    protoc --version
    libprotoc 3.17.3
    
    protoc-gen-go --version
    protoc-gen-go v1.27.1
    
    protoc-gen-go-grpc --version
    protoc-gen-go-grpc 1.1.0
    

    本文基于上面的软件版本进行编码,protoc的不同版本差别较大。

    创建golang项目

    目录结构如下。

    项目目录结构

    在product目录下创建ProductInfo.proto文件

    syntax = "proto3";
    option go_package = ".;product";
    
    service ProductInfo {
      //添加商品
      rpc addProduct(Product) returns (ProductId);
      //获取商品
      rpc getProduct(ProductId) returns (Product);
    }
    
    message Product {
      string id = 1;
      string name = 2;
      string description = 3;
    }
    
    message ProductId {
      string value = 1;
    }
    

    文件定义了两个接口,添加商品、获取商品。定义了2个对象Product、ProductId。

    生成golang语言接口定义

    在product目录下执行下面命令,创建go语言的接口文件

    protoc --go_out=. ProductInfo.proto
    protoc --go-grpc_out=. ProductInfo.proto

    执行完成后会生成ProductInfo.pb.go和ProductInfo_grpc.pb.go两个文件。这两个文件是生成的,不要修改文件内容。

    创建服务端文件

    在product/server文件夹下创建main.go文件

    package main
    
    import (
    	"context"
    	"github.com/gofrs/uuid"
    	"gomicro-quickstart/product"
    	"google.golang.org/grpc"
    	"google.golang.org/grpc/codes"
    	"google.golang.org/grpc/status"
    	"log"
    	"net"
    )
    
    type server struct {
    	productMap map[string]*product.Product
    	product.UnimplementedProductInfoServer
    }
    
    //添加商品
    func (s *server) AddProduct(ctx context.Context, req *product.Product) (resp *product.ProductId, err error) {
    	resp = &product.ProductId{}
    	out, err := uuid.NewV4()
    	if err != nil {
    		return resp, status.Errorf(codes.Internal, "err while generate the uuid ", err)
    	}
    
    	req.Id = out.String()
    	if s.productMap == nil {
    		s.productMap = make(map[string]*product.Product)
    	}
    
    	s.productMap[req.Id] = req
    	resp.Value = req.Id
    	log.Println("AddProduct req.Id:" + req.Id)
    	return
    }
    
    //获取商品
    func (s *server) GetProduct(ctx context.Context, req *product.ProductId) (resp *product.Product, err error) {
    	if s.productMap == nil {
    		s.productMap = make(map[string]*product.Product)
    	}
    
    	resp = s.productMap[req.Value]
    	log.Println("GetProduct ProductName:" + resp.GetName())
    
    	return
    }
    
    const (
    	address = "localhost:50051"
    )
    
    func main() {
    	listener, err := net.Listen("tcp", address)
    	if err != nil {
    		log.Println("net listen err ", err)
    		return
    	}
    
    	s := grpc.NewServer()
    	product.RegisterProductInfoServer(s, &server{})
    	log.Println("start gRPC listen on port " + address)
    	if err := s.Serve(listener); err != nil {
    		log.Println("failed to serve...", err)
    		return
    	}
    }
    
    

    服务端实现了grpc定义的添加商品、获取商品两个接口,并使用50051端口提供服务。

    创建客户端文件

    在product/client文件夹下创建main.go文件

    package main
    
    import (
       "context"
       "gomicro-quickstart/product"
       "google.golang.org/grpc"
       "log"
    )
    
    const (
       address = "localhost:50051"
    )
    
    func main() {
       conn, err := grpc.Dial(address, grpc.WithInsecure())
       if err != nil {
          log.Println("did not connect.", err)
          return
       }
       defer conn.Close()
    
       client := product.NewProductInfoClient(conn)
       ctx := context.Background()
    
       id := AddProduct(ctx, client)
       GetProduct(ctx, client, id)
    }
    
    // 添加一个测试的商品
    func AddProduct(ctx context.Context, client product.ProductInfoClient) (id string) {
       aMac := &product.Product{Name: "Mac Book Pro 2019", Description: "From Apple Inc."}
       productId, err := client.AddProduct(ctx, aMac)
       if err != nil {
          log.Println("add product fail.", err)
          return
       }
       log.Println("add product success, id = ", productId.Value)
       return productId.Value
    }
    
    // 获取一个商品
    func GetProduct(ctx context.Context, client product.ProductInfoClient, id string) {
       p, err := client.GetProduct(ctx, &product.ProductId{Value: id})
       if err != nil {
          log.Println("get product err.", err)
          return
       }
       log.Printf("get prodcut success : %+v
    ", p)
    }
    

    客户端调用添加商品接口后调用获取商品接口。

    运行程序

    先运行服务端程序

    在项目根目录执行

    go run product/server/main.go

    image-20210929154504708

    再运行客户端程序

    在项目根目录执行

    go run product/client/main.go

    image-20210929155100744此时服务端也会有相应的打印输出

    image-20210929155151548

    本文代码

    https://github.com/lts8989/gomicro-quickstart

    参考

    https://segmentfault.com/a/1190000039717888

    https://www.cnblogs.com/hongjijun/p/13724738.html

  • 相关阅读:
    浅尝《Windows核心编程》之 等待函数
    linux 下 解压rar的过程
    一些多线程编程的例子(转)
    js数组操作《转》
    缩略图片处理<收藏>
    .net 框架
    详解NeatUpload上传控件的使用
    NHibernate工具
    xml xpath语法《转》
    C#事务技术
  • 原文地址:https://www.cnblogs.com/lts8989/p/15353293.html
Copyright © 2011-2022 走看看