偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

【Go微服務(wù)】一文帶你玩轉(zhuǎn)ProtoBuf

開發(fā) 前端
通過這篇文章,我們不僅學(xué)會了ProtoBuf的入門操作,還使用Go語言基于ProtoBuf編碼解碼了數(shù)據(jù),進行了實戰(zhàn)。進階部分帶大家了解了ProtoBuf如何定義消息、ProtoBuf和Go數(shù)據(jù)類型的映射、枚舉類型如何使用、通過消息嵌套復(fù)用代碼、使用map類型時需要注意的問題和小技巧。

前言

在網(wǎng)絡(luò)通信和通用數(shù)據(jù)交換等應(yīng)用場景中經(jīng)常使用的技術(shù)是 JSON 或 XML,在微服務(wù)架構(gòu)中通常使用另外一個數(shù)據(jù)交換的協(xié)議的工具ProtoBuf。

ProtoBuf也是我們做微服務(wù)開發(fā),進行Go進階實戰(zhàn)中,必知必會的知道點。

今天就開始第一章內(nèi)容:《一文帶你玩轉(zhuǎn)ProtoBuf》

5分鐘入門

1.1 簡介

你可能不知道ProtoBuf,但一定知道json或者xml,從一定意義上來說他們的作用是一樣的。

ProtoBuf全稱:protocol buffers,直譯過來是:“協(xié)議緩沖區(qū)”,是一種與語言無關(guān)、與平臺無關(guān)的可擴展機制,用于序列化結(jié)構(gòu)化數(shù)據(jù)。

和json\xml最大的區(qū)別是:json\xml都是基于文本格式,ProtoBuf是二進制格式。

ProtoBuf相比于json\XML,更?。? ~ 10倍)、更快(20 ~ 100倍)、更為簡單。

我們只需要定義一次數(shù)據(jù)結(jié)構(gòu),就可以使用ProtoBuf生成源代碼,輕松搞定在各種數(shù)據(jù)流和各種語言中寫入、讀取結(jié)構(gòu)化數(shù)據(jù)。

1.2 安裝

建議大家使用主流版本v3,這是官網(wǎng)下載地址:https://github.com/protocolbuffers/ProtoBuf/releases

注意,不同的電腦系統(tǒng)安裝包是不一樣的:

  • Windows 64位 點這里下載
  • Windows 32位 點這里下載
  • Mac Intel 64位 點這里下載
  • Mac ARM 64位 點這里下載
  • Linux 64位 點這里下載

(公眾號無法跳轉(zhuǎn)到外鏈,點擊文末的閱讀原文可以跳轉(zhuǎn)到下載地址。)

小技巧:Mac查看自己的芯片類型點擊左上角的蘋果圖標(biāo),再點擊關(guān)于本機,就可以查看了。

比如,我的處理器芯片是intel的,下載安裝包之后是這樣的:

bin目錄下的protoc是ProtoBuf的工具集,下文會重點介紹它的使用。

注意:我們需要將下載得到的可執(zhí)行文件protoc所在的 bin 目錄加到我們電腦的環(huán)境變量中。

Mac安裝小技巧

如果你的Mac安裝了brew,安裝ProtoBuf就更簡單了,我們使用brew install ProtoBuf就可以了

1.3 編譯go語言的工具包

這個protoc可以將proto文件編譯為任何語言的文件,想要編譯為go語言的,還需要下載另外一個可執(zhí)行文件

命令是這樣的:

go install google.golang.org/ProtoBuf/cmd/protoc-gen-go@latest

1.4 編寫proto代碼

下面就編寫一個非常簡單,但是五臟齊全的proto代碼,我們再根據(jù)這段代碼生成pb.go文件。

syntax = "proto3";

package hello;

option go_package = "./;hello";

message Say{
int64 id = 1;
string hello = 2;
repeated string word = 3;
}

1.5 生成go代碼

生成go代碼,非常簡單,使用下面的命令就可以了。

切換到.proto文件所在目錄

cd proto/demo/

指定proto源文件,自動生成代碼。

protoc --go_out=. hello.proto

執(zhí)行上面的命令后,我們在項目中就自動生成了一個.pb.go的文件

入門ProtoBuf就是這么的簡單:通過這幾步我們就完成了ProtoBuf的下載、安裝、編寫了一個proto文件,并生成了能用Go語言讀寫ProtoBuf的源代碼。

我們再深入了解一下probuf的用法:

10分鐘進階

下面再帶大家深入了解一下ProtoBuf的知識點,避免在開發(fā)中踩坑。

小技巧:寫proto和寫go最大的區(qū)別是需要在結(jié)尾添加分號的;,在開發(fā)過程中給自己提個醒:如果是寫proto需要加分號,如果是寫go不需要加分號。

以我們上面的proto入門代碼舉例:

1.1 關(guān)鍵字

  • syntax:是必須寫的,而且要定義在第一行;目前proto3是主流,不寫默認(rèn)使用proto2
  • package:定義我們proto文件的包名
  • option go_package:定義生成的pb.go的包名,我們通常在proto文件中定義。如果不在proto文件中定義,也可以在使用protoc生成代碼時指定pb.go文件的包名

message:非常重要,用于定義消息結(jié)構(gòu)體,不用著急,下文會重點講解

細心的小伙伴一定注意到了 message 消息體中有一個 “repeated” 關(guān)鍵字,這在我們寫Go的時候是沒有的。

這是干什么用的呢?下面來詳細解答一下:

1.2 數(shù)組類型

關(guān)于數(shù)組類型,和Java、Go、PHP等語言中,定義數(shù)據(jù)類型不一樣。

在ProtoBuf消息中定義數(shù)組類型,是通過在字段前面增加repeated關(guān)鍵詞實現(xiàn),標(biāo)記當(dāng)前字段是一個數(shù)組。

只要使用repeated標(biāo)記類型定義,就表示數(shù)組類型。

我們來舉兩個例子:

(1)整數(shù)數(shù)組:

下面定義的arrays表示int32類型的數(shù)組

message Msg {
repeated int32 arrays = 1;
}

(2)字符串?dāng)?shù)組

下面定義的names表示字符串?dāng)?shù)組

message Msg {
repeated string names = 1;
}

repeated搞懂了,message又是干嘛用的呢?

1.3 消息

消息(message),在ProtoBuf中指的就是我們要定義的數(shù)據(jù)結(jié)構(gòu)。類似于Go中定義結(jié)構(gòu)體。

message關(guān)鍵詞用法也非常簡單:

(1) 語法

syntax = "proto3";

message 消息名 {
消息體
}

例子:

syntax = "proto3";

message Request {
string query = 1;
int32 page = 2;
int32 limit = 3;
}

定義了一個Request消息,這個消息有3個字段,query是字符串類型,page和limit是int32類型。

1.4 字段類型

ProtoBuf支持多種數(shù)據(jù)類型,例如:string、int32、double、float等等,我整理了一份ProtoBuf和go語言的數(shù)據(jù)類型映射表

.proto Type

Go Type

使用技巧

double

float64

沒特殊技巧,記住float對應(yīng)go的float32,double對應(yīng)go的float64就可以了

float

float32

沒特殊技巧,記住float對應(yīng)go的float32,double對應(yīng)go的float64就可以了

int32

int32

使用變長編碼,對于負值的效率很低,如果你的域有可能有負值,請使用sint64替代

uint32

uint32

使用變長編碼

uint64

uint64

使用變長編碼

sint32

int32

使用變長編碼,這些編碼在負值時比int32高效的多

sint64

int64

使用變長編碼,有符號的整型值。編碼時比通常的int64高效。

fixed32

uint32

總是4個字節(jié),如果數(shù)值都比228大的話,這個類型會比uint32高效。

fixed64

uint64

總是8個字節(jié),如果數(shù)值都比256大的話,這個類型會比uint64高效。

sfixed32

int32

總是4個字節(jié)

sfixed64

int64

總是8個字節(jié)

bool

bool

嚴(yán)格對應(yīng),玩不出其他花樣來

string

string

一個字符串必須是UTF-8編碼或者7-bit ASCII編碼的文本。

bytes

[]byte

可以包含任意順序的字節(jié)數(shù)組

1.5 分配標(biāo)識號

細心的小伙伴可能又有疑問了,上面消息體中的 string query = 1; 這個1是什么呢?

這些數(shù)字是“分配表示號”:在消息定義中,每個字段后面都有一個唯一的數(shù)字,這個就是標(biāo)識號。

這些標(biāo)識號的作用是:用來在消息的二進制格式中識別各個字段的,一旦開始使用就不能夠再改變。

注意:分配標(biāo)識號在每個消息內(nèi)唯一,不同的消息體是可以擁有相同的標(biāo)識號的。

小技巧:[1,15]之內(nèi)的標(biāo)識號在編碼的時候會占用一個字節(jié)。[16,2047]之內(nèi)的標(biāo)識號則占用2個字節(jié)。所以應(yīng)該為那些頻繁出現(xiàn)的消息元素保留 [1,15]之內(nèi)的標(biāo)識號。

1.5.1 保留標(biāo)識號(Reserved)

小技巧:要為將來有可能添加的、頻繁出現(xiàn)的字段預(yù)留一些標(biāo)識號。

我們想保留一些標(biāo)識號,留給以后用,可以使用下面語法:

message Test {
reserved 2, 5, 7 to 10; // 保留2,5,7到10這些標(biāo)識號
}

如果使用了這些保留的標(biāo)識號,protocol buffer編譯器無法編譯通過,將會輸出警告信息。

1.6 將消息編譯成各種語言版本的類庫

編譯器命令格式:

protoc [OPTION] PROTO_FILES

OPTION是命令的選項, PROTO_FILES是我們要編譯的proto消息定義文件,支持多個。

常用的OPTION選項:

--go_out=OUT_DIR            指定代碼生成目錄,生成 Go 代碼
--cpp_out=OUT_DIR 指定代碼生成目錄,生成 C++ 代碼
--csharp_out=OUT_DIR 指定代碼生成目錄,生成 C# 代碼
--java_out=OUT_DIR 指定代碼生成目錄,生成 java 代碼
--js_out=OUT_DIR 指定代碼生成目錄,生成 javascript 代碼
--objc_out=OUT_DIR 指定代碼生成目錄,生成 Objective C 代碼
--php_out=OUT_DIR 指定代碼生成目錄,生成 php 代碼
--python_out=OUT_DIR 指定代碼生成目錄,生成 python 代碼
--ruby_out=OUT_DIR 指定代碼生成目錄,生成 ruby 代碼

因為開篇我們就用Go舉了例子,下面再用Java舉個例子吧:

protoc --java_out=. hello.proto

在當(dāng)前目錄導(dǎo)出java版本的代碼,編譯hello.proto消息,執(zhí)行效果如下:

下載再帶小伙伴們了解一下ProtoBuf的進階知識點吧:枚舉類型、消息嵌套和Map類型。

1.7 枚舉類型

寫Java的同學(xué)枚舉一定用的很溜,但是寫Go的同學(xué)可能有點懵了,Go是不直接支持枚舉的,并沒有Enum關(guān)鍵字。

關(guān)注我,后續(xù)會詳解Go枚舉相關(guān)的知識點,在這篇文章中不做重點介紹。

使用枚舉的場景是這樣的:

當(dāng)定義一個消息類型的時候,可能想為一個字段指定“預(yù)定義值”中的其中一個值,這時候我們就可以通過枚舉實現(xiàn),比如這種:

syntax = "proto3";//指定版本信息,非注釋的第一行

enum SexType //枚舉消息類型,使用enum關(guān)鍵詞定義,一個性別類型的枚舉類型
{
UNKONW = 0; //proto3版本中,首成員必須為0,成員不應(yīng)有相同的值
MALE = 1; //1
FEMALE = 2; //20未知
}

// 定義一個用戶消息
message UserInfo
{
string name = 1; // 姓名字段
SexType sex = 2; // 性別字段,使用SexType枚舉類型
}

運行效果如下:

在實際開發(fā)中,我們需要定義很多的proto,我們?nèi)绾巫龅较⒌膹?fù)用呢?

答案就是:“消息嵌套”

1.8 消息嵌套

我們在開發(fā)Java和PHP時,經(jīng)常嵌套使用類,也可以使用其他類作為自己的成員屬性類型;在開發(fā)Go時經(jīng)常嵌套使用結(jié)構(gòu)體。

在ProtoBuf中同樣支持消息嵌套,可以在一個消息中嵌套另外一個消息,字段類型可以是另外一個消息類型。

我們來看下面3個經(jīng)典示例:

1.8.1 引用其他消息類型的用法

// 定義Article消息
message Article {
string url = 1;
string title = 2;
repeated string tags = 3; // 字符串?dāng)?shù)組類型
}

// 定義ListArticle消息
message ListArticle {
// 引用上面定義的Article消息類型,作為results字段的類型
repeated Article articles = 1; // repeated關(guān)鍵詞標(biāo)記,說明articles字段是一個數(shù)組
}

1.8.2 消息嵌套

類似類嵌套一樣,消息也可以嵌套,比如這樣:

message ListArticle {
// 嵌套消息定義
message Article {
string url = 1;
string title = 2;
repeated string tags = 3;
}
// 引用嵌套的消息定義
repeated Article articles = 1;
}

1.8.3 import導(dǎo)入其他proto文件定義的消息

我們在實際開發(fā)中,通常要定義很多消息,如果都寫在一個proto文件,是不方便維護的。

小技巧:將消息定義寫在不同的proto文件中,在需要的時候可以通過import導(dǎo)入其他proto文件定義的消息。

例子:

創(chuàng)建文件: article.proto

syntax = "proto3";

package nesting;

option go_package = "./;article";

message Article {
string url = 1;
string title = 2;
repeated string tags = 3; // 字符串?dāng)?shù)組類型
}

創(chuàng)建文件: list_article.proto

syntax = "proto3";
// 導(dǎo)入Article消息定義
import "article.proto";

package nesting;

option go_package = "./;article";

// 定義ListArticle消息
message ListArticle {
// 使用導(dǎo)入的Result消息
repeated Article articles = 1;
}

執(zhí)行效果如下,我們順利生成了.pb.go文件:

1.9 map類型

我們在Go語言開發(fā)中,最常用的就是切片類型和map類型了。

切片類型在ProtoBuf中對應(yīng)的就是repeated類型,前面我們已經(jīng)介紹過了。

再重點介紹一下map類型,ProtoBuf也是支持map類型的:

1.9.1 map語法

map<key_type, value_type> map_field = N;

語法非常簡單和通用,但是有幾個問題需要我們注意:

  • key_type可以是任何整數(shù)或字符串類型(除浮點類型和字節(jié)之外的任何標(biāo)量類型)。
  • 注意:枚舉不是有效的key_type。
  • value_type 可以是除另一個映射之外的任何類型。
  • Map 字段不能使用repeated關(guān)鍵字修飾。

1.9.2 map的例子

我們舉個典型的例子:學(xué)生的學(xué)科和分?jǐn)?shù)就適合用map定義:

syntax = "proto3";

package map;

option go_package = "./;score";

message Student{
int64 id = 1; //id
string name = 2; //學(xué)生姓名
map<string, int32> score = 3; //學(xué)科 分?jǐn)?shù)的map
}

運行效果如下: 

再強調(diào)一下:

注意:Map 字段是不能使用repeated關(guān)鍵字修飾。

至此我們已經(jīng)掌握了ProtoBuf的所有知識點,是不是非常簡單清晰呢?

下面我們在Go項目中實戰(zhàn)應(yīng)用一下ProtoBuf,從ProtoBuf中讀取數(shù)據(jù),并且轉(zhuǎn)換為我們常用的結(jié)構(gòu)體

5分鐘實戰(zhàn)

1. 首先我們定義proto文件

我創(chuàng)建了一個demo目錄,創(chuàng)建了名為study_info.proto的文件

syntax = "proto3";

package demo;

option go_package = "./;study";

message StudyInfo {
int64 id = 1; //id
string name = 2; //學(xué)習(xí)的科目名稱
int32 duration = 3; //學(xué)習(xí)的時長 單位秒
map<string, int32> score = 4; //學(xué)習(xí)的分?jǐn)?shù)
}

2. 生成代碼

使用命令生成pb.go文件:

protoc --go_out=. study_info.proto

3.編寫go文件

編寫go文件,讀取ProtoBuf中定義的字段,進行賦值,取值,轉(zhuǎn)成結(jié)構(gòu)體等操作:

proto編碼和解碼的操作和json是非常像的,都使用“Marshal”和“Unmarshal”關(guān)鍵字。

package main

import (
"fmt"
"google.golang.org/ProtoBuf/proto"
study "juejin/ProtoBuf/proto/demo"
)

func main() {
// 初始化proto中的消息
studyInfo := &study.StudyInfo{}

//常規(guī)賦值
studyInfo.Id = 1
studyInfo.Name = "學(xué)習(xí)ProtoBuf"
studyInfo.Duration = 180

//在go中聲明實例化map賦值給ProtoBuf消息中定義的map
score := make(map[string]int32)
score["實戰(zhàn)"] = 100
studyInfo.Score = score

//用字符串的方式:打印ProtoBuf消息
fmt.Printf("字符串輸出結(jié)果:%v\n", studyInfo.String())

//轉(zhuǎn)成二進制文件
marshal, err := proto.Marshal(studyInfo)
if err != nil {
return
}
fmt.Printf("Marshal轉(zhuǎn)成二進制結(jié)果:%v\n", marshal)

//將二進制文件轉(zhuǎn)成結(jié)構(gòu)體
newStudyInfo := study.StudyInfo{}
err = proto.Unmarshal(marshal, &newStudyInfo)
if err != nil {
return
}
fmt.Printf("二進制轉(zhuǎn)成結(jié)構(gòu)體的結(jié)果:%v\n", &newStudyInfo)
}

運行結(jié)果如下:

本文總結(jié)

ProtoBuf作為開發(fā)微服務(wù)必選的數(shù)據(jù)交換協(xié)議,基于二進制傳輸,比json/xml更小,速度更快,使用也非常的簡單。

通過這篇文章,我們不僅學(xué)會了ProtoBuf的入門操作,還使用Go語言基于ProtoBuf編碼解碼了數(shù)據(jù),進行了實戰(zhàn)。

進階部分帶大家了解了ProtoBuf如何定義消息、ProtoBuf和Go數(shù)據(jù)類型的映射、枚舉類型如何使用、通過消息嵌套復(fù)用代碼、使用map類型時需要注意的問題和小技巧。

本文轉(zhuǎn)載自微信公眾號「 程序員升級打怪之旅」,作者「王中陽Go」,可以通過以下二維碼關(guān)注。

轉(zhuǎn)載本文請聯(lián)系「 程序員升級打怪之旅」公眾號。

責(zé)任編輯:武曉燕 來源: 程序員升級打怪之旅
相關(guān)推薦

2022-04-08 09:01:14

CSS自定義屬性前端

2024-06-27 10:50:01

2020-11-17 09:32:57

設(shè)計模式責(zé)任鏈

2020-05-11 14:35:11

微服務(wù)架構(gòu)代碼

2021-09-27 07:39:52

Go初始化函數(shù)package

2022-09-21 16:56:16

設(shè)計模式微服務(wù)架構(gòu)

2023-11-21 08:37:09

2020-10-29 08:55:04

微服務(wù)

2021-05-29 10:11:00

Kafa數(shù)據(jù)業(yè)務(wù)

2022-11-11 19:09:13

架構(gòu)

2023-07-31 08:18:50

Docker參數(shù)容器

2023-11-06 08:16:19

APM系統(tǒng)運維

2023-11-20 08:18:49

Netty服務(wù)器

2022-12-20 07:39:46

2023-12-21 17:11:21

Containerd管理工具命令行

2024-03-26 00:17:51

Go語言IO

2022-02-24 07:34:10

SSL協(xié)議加密

2023-11-08 08:15:48

服務(wù)監(jiān)控Zipkin

2023-10-27 08:15:45

2021-09-13 22:34:56

區(qū)塊鏈新基建數(shù)字化轉(zhuǎn)型
點贊
收藏

51CTO技術(shù)棧公眾號