看到k8s源码里面用到这个东西,感觉和json很相似 学习一下

protobuf 和json差不多 用于 encoding/decoding 数据  github 地址是github.com/golang/protobuf

开始不知道protoc这个二进制执行文件是干啥的,摸索了好一会儿才明白,原来是用于将proto文件编译为对应的程序文件

按照github的例子

1.创建proto文件,实际上就是定义数据结构

package example;

enum FOO { X = 17; };

message Test {
  required string label = 1;
  optional int32 type = 2 [default=77];
  repeated int64 reps = 3;
  optional group OptionalGroup = 4 {
    required string RequiredField = 5;
  }
}

2.通过protoc.exte对.proto进行编码,这里生成了test.pb.go

3.可以编写自己的程序对生成的test.pb.go进行调用

package main

import (
	"fmt"
	"github.com/golang/protobuf/proto"
	"log"
	pb "test/example"
)

func main() {
	//Test对象
	test := &pb.Test{
		Label: proto.String("hello"),
		Type:  proto.Int32(17),
		Reps:  []int64{1, 2, 3},
		Optionalgroup: &pb.Test_OptionalGroup{
			RequiredField: proto.String("good bye"),
		},
	}
	//编码
	data, err := proto.Marshal(test)
	if err != nil {
		log.Fatal("marshaling error: ", err)
	}
	newTest := &pb.Test{}
	//解码
	err = proto.Unmarshal(data, newTest)
	if err != nil {
		log.Fatal("unmarshaling error: ", err)
	}
	// Now test and newTest contain the same data.
	if test.GetLabel() != newTest.GetLabel() {
		log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
	}
	// 查看解码内容
	fmt.Println(string(newTest.String()))
}



4.protobuf对grpc的支持

test.proto

syntax = "proto3";
 
package example;
 
// 定义接口
service Calculate {
  // 加法
  rpc Sum (Request) returns (Reply) {}
  //除法
  rpc Divide (Request) returns (Reply) {}
}
 
// 发送两个数字
message Request {
  int32 num1 = 1;
  int32 num2 = 2;
}
 
// 返回一个数字
message Reply {
  int32 num1 = 1;
}

进行编译

protoc --go_out=plugins=grpc:. *.proto

服务端代码:

package main

import (
	"errors"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"log"
	"net"
	pb "test/example"
)

type server struct{}

// 加法运算
func (s *server) Sum(ctx context.Context, in *pb.Request) (*pb.Reply, error) {
	return &pb.Reply{Num1: in.Num1 + in.Num2}, nil
}

// 除法运算
func (s *server) Divide(ctx context.Context, in *pb.Request) (*pb.Reply, error) {
	// 判断非0
	if in.Num2 == 0 {
		return nil, errors.New("divide by zero")
	}
	return &pb.Reply{Num1: in.Num1 / in.Num2}, nil
}

func main() {
	conn, err := net.Listen("tcp", ":8080")
	if err != nil {
		log.Fatal("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterCalculateServer(s, &server{})
	s.Serve(conn)
}

客户端代码:

package main

import (
	"fmt"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"log"
	pb "test/example"
)

func main() {
	conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure())
	if err != nil {
		log.Fatal("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewCalculateClient(conn)
	num1 := int32(10)
	num2 := int32(1)
	// num2 := int32(0)
	//加法运算
	r, _ := c.Sum(context.Background(), &pb.Request{num1, num2})
	fmt.Printf("%d\n", r.Num1)

	// 除法运算
	r, err = c.Divide(context.Background(), &pb.Request{num1, num2})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%d\n", r.Num1)
}


Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐