我的编程空间,编程开发者的网络收藏夹
学习永远不晚

go语言怎么用Protobuf做数据交换

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

go语言怎么用Protobuf做数据交换

这篇文章主要讲解了“go语言怎么用Protobuf做数据交换”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“go语言怎么用Protobuf做数据交换”吧!

协议缓冲区(Protobufs)像  XML 和 JSON 一样,可以让用不同语言编写并在不同平台上运行的应用程序交换数据。例如,用 Go 编写的发送程序可以在 Protobuf  中对以 Go 表示的销售订单数据进行编码,然后用 Java 编写的接收方可以对它进行解码,以获取所接收订单数据的 Java  表示方式。

与 XML 和 JSON 相比,Protobuf 编码是二进制而不是文本,这会使调试复杂化。但是,正如本文中的代码示例所确认的那样,Protobuf 编码在大小上比 XML 或 JSON 编码要有效得多。

Protobuf 以另一种方式提供了这种有效性。在实现级别,Protobuf 和其他编码系统对结构化数据进行序列化serialize反序列化deserialize。序列化将特定语言的数据结构转换为字节流,反序列化是将字节流转换回特定语言的数据结构的逆运算。序列化和反序列化可能成为数据交换的瓶颈,因为这些操作会占用大量 CPU。高效的序列化和反序列化是 Protobuf 的另一个设计目标。

最近的编码技术,例如 Protobuf 和 FlatBuffers,源自 1990 年代初期的 DCE/RPC(分布式计算环境/远程过程调用Distributed Computing Environment/Remote Procedure Call)计划。与 DCE/RPC 一样,Protobuf 在数据交换中为 IDL(接口定义语言)和编码层做出了贡献。

本文将着眼于这两层,然后提供 Go 和 Java 中的代码示例以充实 Protobuf 的细节,并表明 Protobuf 是易于使用的。

Protobuf 作为一个 IDL 和编码层

像 Protobuf 一样,DCE/RPC 被设计为与语言和平台无关。适当的库和实用程序允许任何语言和平台用于 DCE/RPC  领域。此外,DCE/RPC 体系结构非常优雅。IDL 文档是一侧的远程过程与另一侧的调用者之间的协定。Protobuf 也是以 IDL  文档为中心的。

IDL 文档是文本,在 DCE/RPC 中,使用基本 C 语法以及元数据的语法扩展(方括号)和一些新的关键字,例如 interface。这是一个例子:

[uuid (2d6ead46-05e3-11ca-7dd1-426909beabcd), version(1.0)]interface echo {   const long int ECHO_SIZE = 512;   void echo(      [in]          handle_t h,      [in, string]  idl_char from_client[ ],      [out, string] idl_char from_service[ECHO_SIZE]   );}

该 IDL 文档声明了一个名为 echo 的过程,该过程带有三个参数:类型为 handle_t(实现指针)和 idl_char(ASCII 字符数组)的 [in] 参数被传递给远程过程,而 [out] 参数(也是一个字符串)从该过程中传回。在此示例中,echo 过程不会显式返回值(echo 左侧的 void),但也可以返回值。返回值,以及一个或多个 [out] 参数,允许远程过程任意返回许多值。下一节将介绍 Protobuf IDL,它的语法不同,但同样用作数据交换中的协定。

DCE/RPC 和 Protobuf 中的 IDL 文档是创建用于交换数据的基础结构代码的实用程序的输入:

IDL 文档 —> DCE/PRC 或 Protobuf 实用程序 —> 数据交换的支持代码

作为相对简单的文本,IDL 是同样便于人类阅读的关于数据交换细节的文档(特别是交换的数据项的数量和每个项的数据类型)。

Protobuf 可用于现代 RPC 系统,例如 gRPC;但是 Protobuf 本身仅提供 IDL 层和编码层,用于从发送者传递到接收者的消息。与原本的 DCE/RPC 一样,Protobuf 编码是二进制的,但效率更高。

目前,XML 和 JSON 编码仍在通过 Web 服务等技术进行的数据交换中占主导地位,这些技术利用 Web 服务器、传输协议(例如  TCP、HTTP)以及标准库和实用程序等原有的基础设施来处理 XML 和 JSON 文档。 此外,各种类型的数据库系统可以存储 XML 和  JSON 文档,甚至旧式关系型系统也可以轻松生成查询结果的 XML 编码。现在,每种通用编程语言都具有支持 XML 和 JSON  的库。那么,是什么让我们回到 Protobuf 之类的二进制编码系统呢?

让我们看一下负十进制值 -128。以 2 的补码二进制表示形式(在系统和语言中占主导地位)中,此值可以存储在单个 8 位字节中:10000000。此整数值在 XML 或 JSON 中的文本编码需要多个字节。例如,UTF-8 编码需要四个字节的字符串,即 -128,即每个字符一个字节(十六进制,值为 0x2d0x310x320x38)。XML 和 JSON 还添加了标记字符,例如尖括号和大括号。有关 Protobuf 编码的详细信息下面就会介绍,但现在的关注点是一个通用点:文本编码的压缩性明显低于二进制编码。

在 Go 中使用 Protobuf 的示例

我的代码示例着重于 Protobuf 而不是 RPC。以下是第一个示例的概述:

  • 名为 dataitem.proto 的 IDL 文件定义了一个 Protobuf 消息,它具有六个不同类型的字段:具有不同范围的整数值、固定大小的浮点值以及两个不同长度的字符串。

  • Protobuf 编译器使用 IDL 文件生成 Go 版本(以及后面的 Java 版本)的 Protobuf 消息及支持函数。

  • Go 应用程序使用随机生成的值填充原生的 Go 数据结构,然后将结果序列化为本地文件。为了进行比较, XML 和 JSON 编码也被序列化为本地文件。

  • 作为测试,Go 应用程序通过反序列化 Protobuf 文件的内容来重建其原生数据结构的实例。

  • 作为语言中立性测试,Java 应用程序还会对 Protobuf 文件的内容进行反序列化以获取原生数据结构的实例。

我的网站上提供了该 IDL 文件以及两个 Go 和一个 Java 源文件,打包为 ZIP 文件。

最重要的 Protobuf IDL 文档如下所示。该文档存储在文件 dataitem.proto 中,并具有常规的.proto 扩展名。

示例 1、Protobuf IDL 文档
syntax = "proto3"; package main; message DataItem {  int64  oddA  = 1;  int64  evenA = 2;  int32  oddB  = 3;  int32  evenB = 4;  float  small = 5;  float  big   = 6;  string short = 7;  string long  = 8;}

该 IDL 使用当前的 proto3 而不是较早的 proto2 语法。软件包名称(在本例中为 main)是可选的,但是惯例使用它以避免名称冲突。这个结构化的消息包含八个字段,每个字段都有一个 Protobuf 数据类型(例如,int64string)、名称(例如,oddAshort)和一个等号 = 之后的数字标签(即键)。标签(在此示例中为 1 到 8)是唯一的整数标识符,用于确定字段序列化的顺序。

Protobuf 消息可以嵌套到任意级别,而一个消息可以是另外一个消息的字段类型。这是一个使用 DataItem 消息作为字段类型的示例:

message DataItems {  repeated DataItem item = 1;}

单个 DataItems 消息由重复的(零个或多个)DataItem 消息组成。

为了清晰起见,Protobuf 还支持枚举类型:

enum PartnershipStatus {  reserved "FREE", "CONSTRAINED", "OTHER";}

reserved 限定符确保用于实现这三个符号名的数值不能重复使用。

为了生成一个或多个声明 Protobuf 消息结构的特定于语言的版本,包含这些结构的 IDL 文件被传递到protoc 编译器(可在 Protobuf GitHub 存储库中找到)。对于 Go 代码,可以以通常的方式安装支持的 Protobuf 库(这里以 作为命令行提示符):

% go get github.com/golang/protobuf/proto

将 Protobuf IDL 文件 dataitem.proto 编译为 Go 源代码的命令是:

% protoc --go_out=. dataitem.proto

标志 --go_out 指示编译器生成 Go 源代码。其他语言也有类似的标志。在这种情况下,结果是一个名为 dataitem.pb.go 的文件,该文件足够小,可以将其基本内容复制到 Go 应用程序中。以下是生成的代码的主要部分:

var _ = proto.Marshal type DataItem struct {   OddA  int64   `protobuf:"varint,1,opt,name=oddA" json:"oddA,omitempty"`   EvenA int64   `protobuf:"varint,2,opt,name=evenA" json:"evenA,omitempty"`   OddB  int32   `protobuf:"varint,3,opt,name=oddB" json:"oddB,omitempty"`   EvenB int32   `protobuf:"varint,4,opt,name=evenB" json:"evenB,omitempty"`   Small float32 `protobuf:"fixed32,5,opt,name=small" json:"small,omitempty"`   Big   float32 `protobuf:"fixed32,6,opt,name=big" json:"big,omitempty"`   Short string  `protobuf:"bytes,7,opt,name=short" json:"short,omitempty"`   Long  string  `protobuf:"bytes,8,opt,name=long" json:"long,omitempty"`} func (m *DataItem) Reset()         { *m = DataItem{} }func (m *DataItem) String() string { return proto.CompactTextString(m) }func (*DataItem) ProtoMessage()    {}func init() {}

编译器生成的代码具有 Go 结构 DataItem,该结构导出 Go 字段(名称现已大写开头),该字段与 Protobuf IDL 中声明的名称匹配。该结构字段具有标准的 Go 数据类型:int32int64float32string。在每个字段行的末尾,是描述 Protobuf 类型的字符串,提供 Protobuf IDL 文档中的数字标签及有关 JSON 信息的元数据,这将在后面讨论。

此外也有函数;最重要的是 Proto.Marshal,用于将 DataItem 结构的实例序列化为 Protobuf 格式。辅助函数包括:清除 DataItem 结构的 Reset,生成 DataItem 的单行字符串表示的 String

描述 Protobuf 编码的元数据应在更详细地分析 Go 程序之前进行仔细研究。

Protobuf 编码

Protobuf 消息的结构为键/值对的集合,其中数字标签为键,相应的字段为值。字段名称(例如,oddAsmall)是供人类阅读的,但是 protoc 编译器的确使用了字段名称来生成特定于语言的对应名称。例如,Protobuf IDL 中的 oddAsmall 名称在 Go 结构中分别成为字段 OddASmall

键和它们的值都被编码,但是有一个重要的区别:一些数字值具有固定大小的 32 或 64 位的编码,而其他数字(包括消息标签)则是 varint 编码的,位数取决于整数的绝对值。例如,整数值 1 到 15 需要 8 位 varint 编码,而值 16 到 2047 需要 16 位。varint 编码在本质上与 UTF-8 编码类似(但细节不同),它偏爱较小的整数值而不是较大的整数值。(有关详细分析,请参见 Protobuf 编码指南)结果是,Protobuf 消息应该在字段中具有较小的整数值(如果可能),并且键数应尽可能少,但每个字段至少得有一个键。

下表 1 列出了 Protobuf 编码的要点:

编码示例类型长度
varintint32uint32int64可变长度
fixedfixed32floatdouble固定的 32 位或 64 位长度
字节序列stringbytes序列长度

表 1. Protobuf 数据类型

未明确固定长度的整数类型是 varint 编码的;因此,在 varint 类型中,例如 uint32u 代表无符号),数字 32 描述了整数的范围(在这种情况下为 0 到 232 - 1),而不是其位的大小,该位大小取决于值。相比之下,对于固定长度类型(例如 fixed32double),Protobuf 编码分别需要 32 位和 64 位。Protobuf 中的字符串是字节序列;因此,字段编码的大小就是字节序列的长度。

另一个高效的方法值得一提。回想一下前面的示例,其中的 DataItems 消息由重复的 DataItem 实例组成:

message DataItems {  repeated DataItem item = 1;}

repeated 表示 DataItem 实例是打包的:集合具有单个标签,在这里是 1。因此,具有重复的 DataItem 实例的 DataItems 消息比具有多个但单独的 DataItem 字段、每个字段都需要自己的标签的消息的效率更高。

了解了这一背景,让我们回到 Go 程序。

dataItem 程序的细节

dataItem 程序创建一个 DataItem 实例,并使用适当类型的随机生成的值填充字段。Go 有一个 rand 包,带有用于生成伪随机整数和浮点值的函数,而我的 randString 函数可以从字符集中生成指定长度的伪随机字符串。设计目标是要有一个具有不同类型和位大小的字段值的 DataItem 实例。例如,OddAEvenA 值分别是 64 位非负整数值的奇数和偶数;但是 OddBEvenB 变体的大小为 32 位,并存放 0 到 2047 之间的小整数值。随机浮点值的大小为 32 位,字符串为 16(Short)和 32(Long)字符的长度。这是用随机值填充 DataItem 结构的代码段:

// 可变长度整数n1 := rand.Int63()        // 大整数if (n1 & 1) == 0 { n1++ } // 确保其是奇数...n3 := rand.Int31() % UpperBound // 小整数if (n3 & 1) == 0 { n3++ }       // 确保其是奇数 // 固定长度浮点数...t1 := rand.Float32()t2 := rand.Float32()...// 字符串str1 := randString(StrShort)str2 := randString(StrLong) // 消息dataItem := &DataItem {   OddA:  n1,   EvenA: n2,   OddB:  n3,   EvenB: n4,   Big:   f1,   Small: f2,   Short: str1,   Long:  str2,}

创建并填充值后,DataItem 实例将以 XML、JSON 和 Protobuf 进行编码,每种编码均写入本地文件:

func encodeAndserialize(dataItem *DataItem) {   bytes, _ := xml.MarshalIndent(dataItem, "", " ")  // Xml to dataitem.xml   ioutil.WriteFile(XmlFile, bytes, 0644)            // 0644 is file access permissions    bytes, _ = json.MarshalIndent(dataItem, "", " ")  // Json to dataitem.json   ioutil.WriteFile(JsonFile, bytes, 0644)    bytes, _ = proto.Marshal(dataItem)                // Protobuf to dataitem.pbuf   ioutil.WriteFile(PbufFile, bytes, 0644)}

这三个序列化函数使用术语 marshal,它与 serialize 意思大致相同。如代码所示,三个 Marshal 函数均返回一个字节数组,然后将其写入文件。(为简单起见,忽略可能的错误处理。)在示例运行中,文件大小为:

dataitem.xml:  262 bytesdataitem.json: 212 bytesdataitem.pbuf:  88 bytes

Protobuf 编码明显小于其他两个编码方案。通过消除缩进字符(在这种情况下为空白和换行符),可以稍微减小 XML 和 JSON 序列化的大小。

以下是 dataitem.json 文件,该文件最终是由 json.MarshalIndent 调用产生的,并添加了以 ## 开头的注释:

{ "oddA":  4744002665212642479,                ## 64-bit >= 0 "evenA": 2395006495604861128,                ## ditto "oddB":  57,                                 ## 32-bit >= 0 but < 2048 "evenB": 468,                                ## ditto "small": 0.7562016,                          ## 32-bit floating-point "big":   0.85202795,                         ## ditto "short": "ClH1oDaTtoX$HBN5",                 ## 16 random chars "long":  "xId0rD3Cri%3Wt%^QjcFLJgyXBu9^DZI"  ## 32 random chars}

尽管这些序列化的数据写入到本地文件中,但是也可以使用相同的方法将数据写入网络连接的输出流。

测试序列化和反序列化

Go 程序接下来通过将先前写入 dataitem.pbuf 文件的字节反序列化为 DataItem 实例来运行基本测试。这是代码段,其中去除了错误检查部分:

filebytes, err := ioutil.ReadFile(PbufFile) // get the bytes from the file...testItem.Reset()                            // clear the DataItem structureerr = proto.Unmarshal(filebytes, testItem)  // deserialize into a DataItem instance

用于 Protbuf 反序列化的 proto.Unmarshal 函数与 proto.Marshal 函数相反。原始的 DataItem 和反序列化的副本将被打印出来以确认完全匹配:

Original:2041519981506242154 3041486079683013705 1192 18790.572123 0.326855boPb#T0O8Xd&Ps5EnSZqDg4Qztvo7IIs 9vH66AiGSQgCDxk& Deserialized:2041519981506242154 3041486079683013705 1192 18790.572123 0.326855boPb#T0O8Xd&Ps5EnSZqDg4Qztvo7IIs 9vH66AiGSQgCDxk&

一个 Java Protobuf 客户端

用 Java 写的示例是为了确认 Protobuf 的语言中立性。原始 IDL 文件可用于生成 Java 支持代码,其中涉及嵌套类。但是,为了抑制警告信息,可以进行一些补充。这是修订版,它指定了一个 DataMsg 作为外部类的名称,内部类在该 Protobuf 消息后面自动命名为 DataItem

syntax = "proto3"; package main; option java_outer_classname = "DataMsg"; message DataItem {...

进行此更改后,protoc 编译与以前相同,只是所期望的输出现在是 Java 而不是 Go:

% protoc --java_out=. dataitem.proto

生成的源文件(在名为 main 的子目录中)为 DataMsg.java,长度约为 1,120 行:Java 并不简洁。编译然后运行 Java 代码需要具有 Protobuf 库支持的 JAR 文件。该文件位于 Maven 存储库中。

放置好这些片段后,我的测试代码相对较短(并且在 ZIP 文件中以 Main.java 形式提供):

package main;import java.io.FileInputStream; public class Main {   public static void main(String[] args) {      String path = "dataitem.pbuf";  // from the Go program's serialization      try {         DataMsg.DataItem deserial =           DataMsg.DataItem.newBuilder().mergeFrom(new FileInputStream(path)).build();          System.out.println(deserial.getOddA()); // 64-bit odd         System.out.println(deserial.getLong()); // 32-character string      }      catch(Exception e) { System.err.println(e); }    }}

当然,生产级的测试将更加彻底,但是即使是该初步测试也可以证明 Protobuf 的语言中立性:dataitem.pbuf 文件是 Go 程序对 Go 语言版的 DataItem 进行序列化的结果,并且该文件中的字节被反序列化以产生一个 Java 语言的 DataItem 实例。Java 测试的输出与 Go 测试的输出相同。

用 numPairs 程序来结束

让我们以一个示例作为结尾,来突出 Protobuf 效率,但又强调在任何编码技术中都会涉及到的成本。考虑以下 Protobuf IDL 文件:

syntax = "proto3";package main; message NumPairs {  repeated NumPair pair = 1;} message NumPair {  int32 odd = 1;  int32 even = 2;}

NumPair 消息由两个 int32 值以及每个字段的整数标签组成。NumPairs 消息是嵌入的 NumPair 消息的序列。

Go 语言的 numPairs 程序(如下)创建了 200 万个 NumPair 实例,每个实例都附加到 NumPairs 消息中。该消息可以按常规方式进行序列化和反序列化。

示例 2、numPairs 程序
package main import (   "math/rand"   "time"   "encoding/xml"   "encoding/json"   "io/ioutil"   "github.com/golang/protobuf/proto") // protoc-generated code: startvar _ = proto.Marshaltype NumPairs struct {   Pair []*NumPair `protobuf:"bytes,1,rep,name=pair" json:"pair,omitempty"`} func (m *NumPairs) Reset()         { *m = NumPairs{} }func (m *NumPairs) String() string { return proto.CompactTextString(m) }func (*NumPairs) ProtoMessage()    {}func (m *NumPairs) GetPair() []*NumPair {   if m != nil { return m.Pair }   return nil} type NumPair struct {   Odd  int32 `protobuf:"varint,1,opt,name=odd" json:"odd,omitempty"`   Even int32 `protobuf:"varint,2,opt,name=even" json:"even,omitempty"`} func (m *NumPair) Reset()         { *m = NumPair{} }func (m *NumPair) String() string { return proto.CompactTextString(m) }func (*NumPair) ProtoMessage()    {}func init() {}// protoc-generated code: finish var numPairsStruct NumPairsvar numPairs = &numPairsStruct func encodeAndserialize() {   // XML encoding   filename := "./pairs.xml"   bytes, _ := xml.MarshalIndent(numPairs, "", " ")   ioutil.WriteFile(filename, bytes, 0644)    // JSON encoding   filename = "./pairs.json"   bytes, _ = json.MarshalIndent(numPairs, "", " ")   ioutil.WriteFile(filename, bytes, 0644)    // ProtoBuf encoding   filename = "./pairs.pbuf"   bytes, _ = proto.Marshal(numPairs)   ioutil.WriteFile(filename, bytes, 0644)} const HowMany = 200 * 100  * 100 // two million func main() {   rand.Seed(time.Now().UnixNano())    // uncomment the modulus operations to get the more efficient version   for i := 0; i < HowMany; i++ {      n1 := rand.Int31() // % 2047      if (n1 & 1) == 0 { n1++ } // ensure it's odd      n2 := rand.Int31() // % 2047      if (n2 & 1) == 1 { n2++ } // ensure it's even       next := &NumPair {                 Odd:  n1,                 Even: n2,              }      numPairs.Pair = append(numPairs.Pair, next)   }   encodeAndserialize()}

每个 NumPair 中随机生成的奇数和偶数值的范围在 0 到 20 亿之间变化。就原始数据(而非编码数据)而言,Go 程序中生成的整数总共为 16MB:每个 NumPair 为两个整数,总计为 400 万个整数,每个值的大小为四个字节。

为了进行比较,下表列出了 XML、JSON 和 Protobuf 编码的示例 NumsPairs 消息的 200 万个 NumPair 实例。原始数据也包括在内。由于 numPairs 程序生成随机值,因此样本运行的输出有所不同,但接近表中显示的大小。

编码文件字节大小Pbuf/其它 比例
pairs.raw16MB169%
Protobufpairs.pbuf27MB&mdash;
JSONpairs.json100MB27%
XMLpairs.xml126MB21%

表 2. 16MB 整数的编码开销

不出所料,Protobuf 和之后的 XML 和 JSON 差别明显。Protobuf 编码大约是 JSON 的四分之一,是 XML  的五分之一。但是原始数据清楚地表明 Protobuf 也会产生编码开销:序列化的 Protobuf 消息比原始数据大 11MB。包括  Protobuf 在内的任何编码都涉及结构化数据,这不可避免地会增加字节。

序列化的 200 万个 NumPair 实例中的每个实例都包含个整数值:Go 结构中的 EvenOdd 字段分别一个,而 Protobuf 编码中的每个字段、每个标签一个。对于原始数据(而不是编码数据),每个实例将达到 16 个字节,样本 NumPairs 消息中有 200 万个实例。但是 Protobuf 标记(如 NumPair 字段中的 int32 值)使用 varint 编码,因此字节长度有所不同。特别是,小的整数值(在这种情况下,包括标签在内)需要不到四个字节进行编码。

如果对 numPairs 程序进行了修改,以使两个 NumPair 字段的值小于 2048,且其编码为一或两个字节,则 Protobuf 编码将从 27MB 下降到 16MB,这正是原始数据的大小。下表总结了样本运行中的新编码大小。

编码文件字节大小Pbuf/其它 比例
Nonepairs.raw16MB100%
Protobufpairs.pbuf16MB&mdash;
JSONpairs.json77MB21%
XMLpairs.xml103MB15%

表 3. 编码 16MB 的小于 2048 的整数

总之,修改后的 numPairs 程序的字段值小于 2048,可减少原始数据中每个四字节整数值的大小。但是  Protobuf 编码仍然需要标签,这些标签会在 Protobuf 消息中添加字节。Protobuf  编码确实会增加消息大小,但是如果要编码相对较小的整数值(无论是字段还是键),则可以通过 varint 因子来减少此开销。

对于包含混合类型的结构化数据(且整数值相对较小)的中等大小的消息,Protobuf 明显优于 XML 和 JSON  等选项。在其他情况下,数据可能不适合 Protobuf  编码。例如,如果两个应用程序需要共享大量文本记录或大整数值,则可以采用压缩而不是编码技术。

感谢各位的阅读,以上就是“go语言怎么用Protobuf做数据交换”的内容了,经过本文的学习后,相信大家对go语言怎么用Protobuf做数据交换这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

go语言怎么用Protobuf做数据交换

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

go语言怎么用Protobuf做数据交换

这篇文章主要讲解了“go语言怎么用Protobuf做数据交换”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“go语言怎么用Protobuf做数据交换”吧!协议缓冲区(Protobufs)像
2023-06-16

R语言怎么做数值替换

在R语言中,可以使用以下几种方法进行数值替换:使用ifelse()函数:可以使用ifelse()函数将满足某个条件的数值替换为另一个数值。例如,将大于10的数值替换为100,可以使用以下代码:x 10, 100, x)使用replace
2023-10-26

go语言的复数用来做什么

在go语言中,复数主要用于科学计算上;Go内置有很多科学计算的库,而作为一门泛用编程语言,提供一个方便的复数类型还是挺有必要的。Go语言中复数的类型有两种:complex128(64位实数和虚数)和complex64(32位实数和虚数),其中complex128为复数的默认类型。
2023-05-14

C语言怎么交换两个数的值

本文小编为大家详细介绍“C语言怎么交换两个数的值”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言怎么交换两个数的值”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。使用临时变量以下实例演示了交换两个浮点数的值。
2023-06-17

云服务器与云数据库怎么做数据交换

云服务器和云数据库都是将数据从一台计算机传输到另一台计算机上的工具,但云服务器通常会提供一些附加功能,如数据传输功能、存储功能和备份功能。下面是一些云服务器和云数据库可能会涉及的数据交换的方式:数据传输功能:将数据从一台计算机传输到另一台计算机上需要进行数据传输功能。通常需要使用HTTP/Socket等协议来实现数据传输。在云服务器中,通常会提供HTTPS/SSL等加密传输服务以确保数据的安
2023-10-26

云服务器与云数据库怎么做数据交换的

云服务器与云数据库之间的数据交换是通过API进行的,API是一种云计算服务提供商提供的API或接口,它可以让云服务器管理者和云数据库管理员之间共享资源和数据。以下是一个简单的API示例,可以使云服务器与云数据库之间的数据交换:```pythonimportre云服务器管理者将数据库连接信息和API密钥保存在一个数据文件中data_file='example.mdb'云数据库管理员将数据从数据文件中读取并保存到数据仓库中dbmsfiletotable=datafi...
2023-10-27

c语言中怎么交换两个数的值

在C语言中,可以使用几种方法来交换两个数的值。1. 使用第三个变量:```cint a = 5;int b = 10;int temp;temp = a;a = b;b = temp;```2. 使用加减法:```cint a = 5;in
2023-08-11

云服务器与云数据库怎么做数据交换系统

云服务器与云数据库的数据交换系统需要考虑数据的存储、访问和传输等方面。以下是一些一般性的考虑:数据存储在云服务器的数据存储中,可以选择将数据存储在多个节点上,而不是只存储在一个云服务器上。这样可以使得数据传输更加便捷和高效,可以将数据存储到不同的云服务器的多个节点上。数据访问在云服务器的数据访问中,需要考虑数据的访问方式。可以采用多种方式进行数据访问,例如,可以通过API方式(例如GoogleCloudAPI)进行...
2023-10-27

Go语言怎么使用Gob传输数据

这篇文章主要讲解了“Go语言怎么使用Gob传输数据”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go语言怎么使用Gob传输数据”吧!为了让某个数据结构能够在网络上传输或能够保存至文件,它必须
2023-07-05

go语言怎么连接数据库

go语言通过导入数据库驱动、建立数据库连接、执行SQL语句、使用预处理语句和事务处理处理等步骤来连接数据库。详细介绍:1、导入数据库驱动,使用github.com/go-sql-driver/mysql包来连接MySQL数据库;2、建立数据
go语言怎么连接数据库
2023-12-12

如何使用Go语言和Redis做实时数据分析

如何使用Go语言和Redis做实时数据分析概述:随着大数据时代的到来,数据分析在企业决策中的重要性越来越凸显。而实时数据分析则成为了更加流行和需要的技术方法。本文将介绍如何使用Go语言和Redis实现实时数据分析,并提供具体的代码示例。Re
2023-10-27

go语言数据库中间件怎么使用

Go语言数据库中间件的使用方法有以下几个步骤:1. 引入数据库驱动包:根据所选中间件的类型,引入对应的数据库驱动包。例如,如果选择使用MySQL数据库,可以使用"github.com/go-sql-driver/mysql"包。2. 建立数
2023-10-20

云服务器与云数据库怎么做数据交换系统设计

数据收集:SDN将数据分成不同的颗粒度,可以将数据分发到不同的节点,并且对每个节点进行控制和管理。SDN可以实现网络的自组织和自治,以便更好地管理和控制数据交换系统。数据存储:SDN可以实现数据的存储和交换,以及对数据进行安全性和可靠性的保障。SDN可以通过自动化的方式,将数据存储到不同的节点,并且对数据进行加密和保护。数据传输:SDN可以实现数据的传输,以及对数据进行安全性和可靠性的保障。SDN...
2023-10-27

Go语言的数组怎么用

本篇内容介绍了“Go语言的数组怎么用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!数组变量的定义我们先试一下只申明类型,不赋初值。这时编译器
2023-06-02

Go语言中数组怎么用

这篇文章主要介绍Go语言中数组怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!概述固定长度,数组声明后长度便不能再修改只能存储一种特定类型元素的序列语法编号方式代码示例1直接声明var arr [3]int2ma
2023-06-25

go语言怎么调用函数

本文小编为大家详细介绍“go语言怎么调用函数”,内容详细,步骤清晰,细节处理妥当,希望这篇“go语言怎么调用函数”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。在go语言中,定义了函数之后,我们可以通过“函数名()
2023-07-04

Go语言中整数类型之间怎么转换

这篇“Go语言中整数类型之间怎么转换”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Go语言中整数类型之间怎么转换”文章吧。G
2023-07-05

go语言搭载什么数据库使用

go语言常见搭载的数据库有“MySQL”、“PostgreSQL”、“SQLite”、“MongoDB”和“Redis”五种:1、MySQL,一种开源的关系型数据库管理系统,Go语言提供了官方的MySQL驱动程序;2、PostgreSQL,
go语言搭载什么数据库使用
2023-12-18

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录