golang-protobuf_go的内置rpc_grpc的配置和使用 - Go语言中文社区

golang-protobuf_go的内置rpc_grpc的配置和使用


protobuf配置和使用

  • 下载对应zip包, 解压
    https://github.com/protocolbuffers/protobuf/releases

  • 配置环境变量:
    在用户系统变量Path最后添加刚刚解压的bin目录,例如: G:softprotobufbin

  • 验证是否配置正确:
    打开终端,输入protoc,如果输出下面内容,代码配置成功。
    在这里插入图片描述

  • 安装protoc-gen-go库
    在此之前要设置go的环境变量:

    • GO111MODULE=on
    • GOPROXY=https://goproxy.cn,direct
      然后:
      go get github.com/golang/protobuf/protoc-gen-go
  • 定义test.proto文件, 输入下面数据 :


syntax = "proto3"; 	//proto版本信息
package test;    //定义属于哪个包

//如果报waring就加上这个,不加也能成功
// ./aaa - 表示生成的go文件的存放地址,会自动生成目录的
// test - 表示生成的go文件所属的包名
option go_package = "./aaa;test";	

//message是固定格式,表示消息,  Order是数据对象的名
// required - 必填项,  optional - 选填项, 这两个是proto2的参数,在proto3取消了
// = 1, = 2, = 3是字段的顺序, 为了保证数据顺序的统一
message Order{
    int32 order_id = 1;
    int64 num = 2;
    name = 3;
}
  • 进入test.proto所在路径, 编译proto文件

    • .指的是编译后的文件路径, 这里使用当前路径就行,具体路径在proto文件里面定义了
    • test.proto指要编译的文件
      注意 = 后面不能有空格
      protoc --go_out =. test.proto
  • 注意,如果要编译grpc可用的proto,需要使用如下命令
    protoc --go_out=plugins=grpc:. test.proto
    proto文件的 package test下面需要加上 :
    option go_package = “./;test”;

  • 使用上面生成的 test.pb.go文件进行数据封包和拆包

func main(){
	fmt.Println("hey_wei_gou")

	//创建消息对象
	msg_test := &test.Order{
		OrderId: *proto.Int32(12),
		Num: *proto.Int64(22),
		Name: *proto.String("fuck"),
	}

	//序列化
	msgDataEncoding,err := proto.Marshal(msg_test)
	if err!=nil{
		fmt.Println("err:",err.Error())
		panic(err)
		return
	}

	//反序列化
	msgEmpty := test.Order{}
	err = proto.Unmarshal(msgDataEncoding,&msgEmpty)
	if err!=nil{
		fmt.Println("err:",err.Error())
		panic(err)
		return
	}

	fmt.Println("order_id:",msgEmpty.GetOrderId())
	fmt.Println("num:",msgEmpty.GetNum())
	fmt.Println("name:",msgEmpty.GetName())
}

go内置rpc的使用

一图胜千言
在这里插入图片描述
上代码:

  • message.proto :

    syntax = "proto3";
    package message;
    option go_package = ".;message";
    
    //订单请求参数
    message OrderRequest{
        string orderId = 1;
        int64 timeStamp = 2;
    }
    
    //订单信息
    message OrderInfo{
        string OrderId = 1;
        string OrderName = 2;
        string OrderStatus = 3;
    }
    
    
  • server.go

package main

import (
	"errors"
	"net"
	"net/http"
	"net/rpc"
	"testRPC/rpcAndProto/message"
	"time"
)

type OrderService struct {
}

func (os *OrderService) GetOrderInfo(request message.OrderRequest, response *message.OrderInfo)error{
	//创建订单信息
	orderMap := map[string]message.OrderInfo{
		"1":{OrderId: "1",OrderName: "衣服",OrderStatus: "已付款"},
		"2":{OrderId: "2",OrderName: "手机",OrderStatus: "未付款"},
		"3":{OrderId: "3",OrderName: "电脑",OrderStatus: "已付款"},
	}

	//得到当前时间
	current := time.Now().Unix()
	if (request.TimeStamp>current){
		//返回异常
		*response = message.OrderInfo{OrderId: "0",OrderName: "",OrderStatus: "订单信息异常"}
	}else {
		result := orderMap[request.OrderId]
		if (result.OrderId!=""){
			//找到对应的d订单id,返回正常数据
			*response = orderMap[request.OrderId]
		}else {
			return errors.New("server error")
		}
	}

	return nil
}

func main(){
	//1.初始化结构指针
	orderServer := new(OrderService)

	//2.调用net/rpc包里面的功能进行服务对象注册
	err := rpc.RegisterName("routeName",orderServer)
	if err!=nil{
		panic(err.Error())
	}

	//3.下面的函数可以把 machUtil里面包含的功能函数注册到HTTP协议中,调用者可以使用http方式进行数据传输
	rpc.HandleHTTP()
	//4.监听
	listen,err := net.Listen("tcp",":8081")
	if err!=nil{
		panic(err.Error())
	}

	//5.处理请求
	http.Serve(listen,nil)
}
  • client.go
package main

import (
	"fmt"
	"net/rpc"
	"testRPC/rpcAndProto/message"
	"time"
)

func main(){
	//1.链接服务器
	client,err := rpc.DialHTTP("tcp","localhost:8081")
	if err!=nil{
		panic(err.Error())
	}

	//2.封装请求
	timeStamp := time.Now().Unix()
	requset := message.OrderRequest{OrderId: "2",TimeStamp: timeStamp}

	var response *message.OrderInfo		//声明接受参数

	//3.同步调用
	err = client.Call("routeName.GetOrderInfo",requset,&response)
	if err!=nil{
		panic(err.Error())
	}
	fmt.Println("resp.OrderId:",response.OrderId)
	fmt.Println("resp.OrderName:",response.OrderName)
	fmt.Println("resp.OrderStatus:",response.OrderStatus)
}

编译proto,运行server.go 再运行 client.go, 齐活…


grpc使用

  • 首先要安装grpc,怎么安装这里不赘述了,直接上代码, 文件结构和上面内置rpc的结构一样
  • message.proto:
syntax = "proto3";
package message;
option go_package = ".;message";

//订单请求参数
message OrderRequest{
    string orderId = 1;
    int64 timeStamp = 2;
}

//订单信息
message OrderInfo{
    string OrderId = 1;
    string OrderName = 2;
    string OrderStatus = 3;
}

//声明服务的方法(函数), GetOrderInfo-函数, OrderRequest-请求参数,OrderInfo-返回参数
//OrderService是服务名,在对应的pb.go里面,会有注册这个服务的对应函数, RegisterOrderServiceServer
service OrderService{
    rpc GetOrderInfo(OrderRequest) returns (OrderInfo);
}


  • server.go
package main

import (
	"context"
	"errors"
	"fmt"
	"net"
	"net/rpc"
	"test_grpc/message"
	"time"

	"google.golang.org/grpc"
)

type OrderServiceImpl struct {
}

func (os *OrderServiceImpl) GetOrderInfo(ctx context.Context,
	request *message.OrderRequest)(*message.OrderInfo,error){
	//创建订单信息
	orderMap := map[string]message.OrderInfo{
		"1":{OrderId: "1",OrderName: "衣服",OrderStatus: "已付款"},
		"2":{OrderId: "2",OrderName: "手机",OrderStatus: "未付款"},
		"3":{OrderId: "3",OrderName: "电脑",OrderStatus: "已付款"},
	}

	//得到当前时间
	current := time.Now().Unix()
	if (request.TimeStamp>current){
		//返回异常
		return &message.OrderInfo{OrderId: "0",OrderName: "",OrderStatus: "订单信息异常"},errors.New("timeout")
	}else {
		result := orderMap[request.OrderId]
		if (result.OrderId!=""){
			//找到对应的d订单id,返回正常数据
			fmt.Println("result:",result)
			return &result,nil
		}else {
			return nil, errors.New("server error")
		}
	}

	return nil,nil
}

func main(){
	//1.初始化grpc
	server := grpc.NewServer()

	message.RegisterOrderServiceServer(server,new(OrderServiceImpl))

	//3.下面的函数可以把 machUtil里面包含的功能函数注册到HTTP协议中,调用者可以使用http方式进行数据传输
	rpc.HandleHTTP()
	//4.监听
	listen,err := net.Listen("tcp",":8090")
	if err!=nil{
		panic(err.Error())
	}

	//5.处理请求
	_ = server.Serve(listen)
}


  • client.go
package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"test_grpc/message"
	"time"
)

func main(){
	//1.链接服务器
	conn,err := grpc.Dial("localhost:8090",grpc.WithInsecure())
	if err!=nil{
		panic(err.Error())
	}
	defer conn.Close()

	//创建连接
	orderServiceClient := message.NewOrderServiceClient(conn)
	//构造请求参数
	orderRequest := &message.OrderRequest{
		OrderId: "3",
		TimeStamp: time.Now().Unix(),
	}
	//发送请求并且得到回参
	orderInfo,err := orderServiceClient.GetOrderInfo(context.Background(),orderRequest)
	if err!=nil{
		panic(err.Error())
	}
	if orderInfo!=nil{
		fmt.Println("orderID:",orderInfo.OrderId)
		fmt.Println("orderName:",orderInfo.OrderName)
		fmt.Println("orderName:",orderInfo.OrderStatus)
	}
}

编译proto,运行server.go 再运行 client.go, 齐活…
注意,注意,编译grpc可用的proto命令如下:
protoc --go_out=plugins=grpc:. xxx.proto

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_41395435/article/details/114868617
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢