前後端數據交互利器–Protobuf

Protobuf 介紹

Protocol Buffers(又名 protobuf)是 Google 的語言中立、平台中立、可擴展的結構化數據序列化機制。
//github.com/protocolbuffers/protobuf

簡而言之,Protobuf 是 Google 開源的一款用於處理前後端數據交互格式的工具。通常來講前後端使用的編程語言是不同的,使用 Protobuf無需多慮,前後端只管約定通信協議,之後就可以使用 pb 工具生成代碼。

ProtoBuf 使用實戰

下載Protobuf

直接上Github 下載最新發行版,注意選擇自己電腦的平台。
筆者使用的環境是 Ubuntu 20.10,也就是linux,下面是下載鏈接

 wget //github.com/protocolbuffers/protobuf/releases/download/v3.17.3/protoc-3.17.3-linux-x86_64.zip

安裝Protobuf

首先執行上條命令下載Protobuf,新建一個文件夾作為解壓目錄

mkdir protoc 
unzip protoc-3.17.3-linux-x86_64.zip -d ./protoc

配置環境變量

這裡的路徑需要根據自身情況進行修改

vim ~/.bashrc 
export PATH="$PATH:/[替換成protoc所處的路徑]/protoc/bin"
source ~./bashrc

使用Protobuf

這裡使用Golang 進行演示

  • 使用golang還需要額外安裝一些插件,這裡貼出插件鏈接,也可以直接使用下面命令進行下載
插件鏈接: //github.com/grpc-ecosystem/grpc-gateway

一鍵式安裝:go get\
    github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \
    github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \
    google.golang.org/protobuf/cmd/protoc-gen-go \
    google.golang.org/grpc/cmd/protoc-gen-go-grpc

這時候檢查你的go/bin 目錄下就會多出以上幾個程序 
如果不知道自己go/bin 路徑,可以通過 go env 查看 

$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN="/xxx/go/bin"

定義消息的格式

  1. syntax 指定proto 版本
  2. package 指定包名
  3. proto 生成的路徑
  4. 其餘可以查看下面代碼進行參考
創建 proto 文件hello.proto 文件內容如下:

syntax = "proto3";
package hello;

option go_package = "hello/proto/gen/go;hello";

message ProtoInfo {
    string version = 1;
}
enum ProtoEnum {
    HELLO_ONE = 0;
    HELLO_TWO = 1;
}

message Hello {
    string first = 1;
    string second = 2;
    int64 number_int64 = 3;
    ProtoInfo proto_info  = 4;//複合類型 
    repeated int32 array_int32 = 5;//數組 
    ProtoEnum proto_enum = 6;
}

生成pb 文件

protoc -I=. --go_out=paths=source_relative:gen/go hello.proto 

protobuf demo

執行生成命令後會生成pb 文件,接下來看一下在項目中如何使用吧

package main

import (
	"encoding/json"
	"fmt"
	hello "hello/proto/gen/go"

	"google.golang.org/protobuf/proto"
)

func main() {
	helloProto := hello.Hello{
		First:       "first",
		Second:      "second",
		NumberInt64: 111,
		ProtoInfo: &hello.ProtoInfo{
			Version: "3",
		},
		ArrayInt32: []int32{1, 2, 3, 4, 5, 6},
		ProtoEnum:  hello.ProtoEnum_HELLO_TWO,
	}
	fmt.Printf("hello:%+v\n", &helloProto)

	//轉成二進制流
	b, err := proto.Marshal(&helloProto)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%X\n", b)

	//從二進制流轉成結構體
	var hello2 hello.Hello
	err = proto.Unmarshal(b, &hello2)
	if err != nil {
		panic(err)
	}
	fmt.Printf("hello2:%+v\n", &hello2)

	//轉成json
	jsonByte, err := json.Marshal(&hello2)
	if err != nil {
		panic(err)
	}
	fmt.Printf("string(jsonByte):%+v\n", string(jsonByte))

}

可以看到生成的pb 文件不僅支持二進制傳輸,同時也支持json 格式
運行demo得到如下結果:


hello:first:"first"  second:"second"  number_int64:111  proto_info:{version:"3"}  array_int32:1  array_int32:2  array_int32:3  array_int32:4  array_int32:5  array_int32:6  proto_enum:HELLO_TWO
0A05666972737412067365636F6E64186F22030A01332A060102030405063001
hello2:first:"first"  second:"second"  number_int64:111  proto_info:{version:"3"}  array_int32:1  array_int32:2  array_int32:3  array_int32:4  array_int32:5  array_int32:6  proto_enum:HELLO_TWO
string(jsonByte):{"first":"first","second":"second","number_int64":111,"proto_info":{"version":"3"},"array_int32":[1,2,3,4,5,6],"proto_enum":1}

Tags: