社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
下载对应zip包, 解压
https://github.com/protocolbuffers/protobuf/releases
配置环境变量:
在用户系统变量Path最后添加刚刚解压的bin目录,例如: G:softprotobufbin
验证是否配置正确:
打开终端,输入protoc,如果输出下面内容,代码配置成功。
安装protoc-gen-go库
在此之前要设置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文件
注意,如果要编译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())
}
一图胜千言
上代码:
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)
}
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, 齐活…
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);
}
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)
}
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
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!