定义一个protobuf消息并生成Go代码

2023-05-16

大家好! 让我们开始gRPC课程的动手部分。 整个部分的目标是构建“个人计算机” Web服务,该服务将使我们能够管理和搜索笔记本电脑配置。

Here's the link to the full gRPC course playlist on Youtube
Gitlab repository: pcbook-go and pcbook-java

Protocol buffer basics

在本讲座中,我们将学习如何编写具有一些基本数据类型的简单协议缓冲区消息,安装Visual Studio Code插件以与protobuf一起使用,最后,我们将安装协议缓冲区编译器并编写Makefile来运行以下代码的生成 走。

但是在开始之前,请确保已启动Go和Visual Studio Code并在计算机上正常运行。 如果没有,您可以观看我的教程视频,了解如何安装Go和设置Visual Studio代码:

本教程将逐步指导您安装Go,并添加箱子文件夹到您的路径,安装Visual Studio Code,自定义其主题并设置Go扩展来使用它。

一切准备就绪后,您可以回到这里继续本讲座。

Install vscode plugins

好吧,让我们从创建一个新项目开始。 首先,我将在中创建一个简单的hello-world程序main.go文件并运行它,只是为了确保Go正常工作。

package main

import "fmt"

func main() {
    fmt.Println("Hello world")
}

然后创建一个名为协议,然后添加一个processor_message.proto文件下。

pcbook
├── proto
│   └── processor_message.proto
└── main.go

Vscode将要求我们为proto文件安装扩展名。 因此,我们去市场搜索ext:proto

Search for ext:proto

我们应该安装两个显示在顶部的扩展:lang格式和vscode-proto3。 让我们为它们两个都单击安装。

How to define a protobuf message

现在回到我们的原始文件。 该文件将包含膝上型计算机的CPU的消息定义。

我们从语法=“ proto3”。

At the moment, there are 2 versions of protocol buffer on Google's official documentation: proto2 and proto3. For simplicity, we will only use proto3 (the newer version) in this course.

语法非常简单,只需使用信息 keyword followed by the name of the 信息. Then inside the 信息 block, we define all of its fields as shown in this picture:

How to write protubuf message

请注意,消息的名称应为UpperCamelCase,字段的名称应为lower_snake_case。

There are many built-in scalar-value data types that we can use, for instance: string, bool, byte, float, double, and many other integer types. We can also use our own data types, such as enums or other messages.

每个消息字段应分配一个唯一的标签。 标签比字段名更重要,因为protobuf将使用它来序列化消息。

标签只是一个任意整数,其最小值为1,最大值为229-1,但19000到19999之间的数字除外,因为它们保留用于内部协议缓冲区实现。

请注意,从1到15的标签仅需要1个字节进行编码,而从16到2047的标签则需要2个字节。 因此,您应该明智地使用它们,例如:将1到15的标签保存在非常频繁出现的字段中。

请记住,标记不必按顺序排列(或顺序排列),但对于消息的相同级别字段,它们必须是唯一的。

Define the CPU message

现在,让我们回到原始文件并定义CPU消息。

syntax = "proto3";

message CPU {
  string brand = 1;
  string name = 2;
  uint32 number_cores = 3;
  uint32 number_threads = 4;
  double min_ghz = 5;
  double max_ghz = 6;
}

CPU将具有品牌类型串,例如“ Intel”,名称也应为类型串,例如“ Core i7-9850”。

我们需要跟踪CPU拥有多少个内核或线程。 它们不能为负,所以让我们使用uint32这里。

接下来,它具有最小和最大频率,例如2.4 GHz或类似的频率。 所以我们可以使用双在此输入。

Generate Go codes

现在,我们已经完成了第一个protobuf消息。 我们如何从中生成Go代码?

First, we need to install protocol buffer compiler (or protoc). On macOS, we can easily do that with the help of Homebrew.

您可以使用以下简单命令安装Homebrew:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

一旦安装了Homebrew,就可以运行此命令进行安装协议:

brew install protobuf

我们可以通过运行以下命令来检查其是否正常工作协议命令。

Next we will go to grpc.io to copy and run 2 commands to install 2 libraries: the golang grpc library and the protoc-gen-go library.

go get -u google.golang.org/grpc
go get -u github.com/golang/protobuf/protoc-gen-go

现在我们都准备好了! 我将创建一个名为铅存储生成的Go代码。

pcbook
├── proto
│   └── processor_message.proto
├── pb
└── main.go

然后运行以下命令来生成代码:

protoc --proto_path=proto proto/*.proto --go_out=plugins=grpc:pb

我们的原始文件位于原型文件夹,所以我们告诉原型c在该文件夹中查找。

随着出去参数,我们告诉协议使用grpc插件生成Go代码,并将其存储在铅我们之前创建的文件夹。

现在,如果我们在vscode中打开该文件夹,我们将看到一个新文件processor_message。pb。go。

pcbook
├── proto
│   └── processor_message.proto
├── pb
│   └── processor_message.pb.go
└── main.go

看看内部,有一个CPU结构和所有字段,这些字段具有我们在协议缓冲区文件中定义的正确数据类型。

const _ = proto.ProtoPackageIsVersion3

type CPU struct {
    Brand                string   `protobuf:"bytes,1,opt,name=brand,proto3" json:"brand,omitempty"`
    Name                 string   `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
    NumberCores          uint32   `protobuf:"varint,3,opt,name=number_cores,json=numberCores,proto3" json:"number_cores,omitempty"`
    NumberThreads        uint32   `protobuf:"varint,4,opt,name=number_threads,json=numberThreads,proto3" json:"number_threads,omitempty"`
    MinGhz               float64  `protobuf:"fixed64,5,opt,name=min_ghz,json=minGhz,proto3" json:"min_ghz,omitempty"`
    MaxGhz               float64  `protobuf:"fixed64,6,opt,name=max_ghz,json=maxGhz,proto3" json:"max_ghz,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}

func (m *CPU) Reset()         { *m = CPU{} }
func (m *CPU) String() string { return proto.CompactTextString(m) }
func (*CPU) ProtoMessage()    {}
func (*CPU) Descriptor() ([]byte, []int) {
    return fileDescriptor_466578cecc6db379, []int{0}
}

func (m *CPU) XXX_Unmarshal(b []byte) error {
    return xxx_messageInfo_CPU.Unmarshal(m, b)
}
func (m *CPU) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
    return xxx_messageInfo_CPU.Marshal(b, m, deterministic)
}
func (m *CPU) XXX_Merge(src proto.Message) {
    xxx_messageInfo_CPU.Merge(m, src)
}
func (m *CPU) XXX_Size() int {
    return xxx_messageInfo_CPU.Size(m)
}
func (m *CPU) XXX_DiscardUnknown() {
    xxx_messageInfo_CPU.DiscardUnknown(m)
}

var xxx_messageInfo_CPU proto.InternalMessageInfo

func (m *CPU) GetBrand() string {
    if m != nil {
        return m.Brand
    }
    return ""
}

func (m *CPU) GetName() string {
    if m != nil {
        return m.Name
    }
    return ""
}

func (m *CPU) GetNumberCores() uint32 {
    if m != nil {
        return m.NumberCores
    }
    return 0
}

func (m *CPU) GetNumberThreads() uint32 {
    if m != nil {
        return m.NumberThreads
    }
    return 0
}

func (m *CPU) GetMinGhz() float64 {
    if m != nil {
        return m.MinGhz
    }
    return 0
}

func (m *CPU) GetMaxGhz() float64 {
    if m != nil {
        return m.MaxGhz
    }
    return 0
}

gRPC在内部使用了一些特殊字段来序列化消息,但是我们不需要关心它们。 还生成了一些有用的getter函数。 所以看起来很棒!

Write a Makefile

我们用来生成代码的命令很长,因此在更新原型文件并想要重新生成代码时,键入该命令不太方便。 因此,让我们用一个简单的命令创建一个Makefile来做到这一点。

pcbook
├── proto
│   └── processor_message.proto
├── pb
│   └── processor_message.pb.go
├── main.go
└── Makefile

在此Makefile中,我们添加了一个gen任务运行代码生成命令,一个清洁随时删除所有生成的go文件的任务,以及跑 task to 跑 the main.go文件。

gen:
    protoc --proto_path=proto proto/*.proto --go_out=plugins=grpc:pb

clean:
    rm pb/*.go 

run:
    go run main.go

我们可以在终端中尝试它们。

Run make commands

当我们跑步弄干净,生成的文件将被删除。

当我们跑步使一代,文件将在中重新生成铅夹。

最后,当我们跑步时奔跑,打印“ Hello world”。

What's next

好,现在您知道如何定义简单的协议缓冲区消息并从中生成Go代码。 在下一个讲座中,我们将深入研究并学习protobuf的更多高级功能。

谢谢阅读! 祝您编程愉快,一会见!

from: https://dev.to//techschoolguru/how-to-define-a-protobuf-message-and-generate-go-code-4g4e

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

定义一个protobuf消息并生成Go代码 的相关文章

随机推荐