专栏
天翼云开发者社区

go proto3简介

2024-04-25 15:30:46 5阅读

简介

在Go中使用Protocol Buffers的proto3版本,你首先需要定义.proto文件来描述你的消息格式,然后使用protoc编译器来生成Go代码。具有高效自动化解析和生成的能力,同时其压缩比例高,可以节省空间,提高效率。

编译

  • 定义.proto文件
syntax = "proto3";

package example;

// MyMessage is the message type.
message MyMessage {
  string data = 1;
}

使用protoc编译器生成Go代码。假设你已经安装了Protocol Buffers编译器

protoc --go_out=./ --go-grpc_out=. product.proto

这将在当前目录下生成一个message.pb.go文件,该文件包含了你定义的MyMessage消息类型的Go表示。

接下来,在Go代码中你可以使用生成的代码来序列化和反序列化消息:

package main

import (
    "fmt"
    "log"

    "your_project_path/example" // Replace with the actual import path for your generated code
)

func main() {
    // Create a new instance of MyMessage
    message := &example.MyMessage{
        Data: "Hello, Proto3!",
    }

    // Serialize the message to a byte array
    serializedMessage, err := proto.Marshal(message)
    if err != nil {
        log.Fatalf("Failed to serialize message: %v", err)
    }

    fmt.Printf("Serialized message: %x\n", serializedMessage)

    // Deserialize the message from the byte array
    newMessage := &example.MyMessage{}
    if err := proto.Unmarshal(serializedMessage, newMessage); err != nil {
        log.Fatalf("Failed to deserialize message: %v", err)
    }

    fmt.Printf("Deserialized message: %s\n", newMessage.Data)
}

在这个例子中,我们首先创建了一个MyMessage的实例,并使用proto.Marshal函数将其序列化为字节数组。然后,我们使用proto.Unmarshal函数将字节数组反序列化为一个新的MyMessage实例。

确保将your_project_path/example替换为实际生成代码的导入路径。如果你的.proto文件和Go代码不在同一个包中,你可能需要调整导入路径以正确引用生成的代码。

注意,从proto3开始,Go生成的代码不再使用Get和Set方法来访问字段,而是直接使用字段名。此外,proto3不再支持字段的required标记,所有字段都是可选的。如果字段未被设置,其值将是该字段类型的零值

语法

Proto3语法的基本结构由三部分组成,分别是package、message和field。其中,message用于定义消息格式,类似于Java中的类定义。

  • optional:可选 自动变成指针
  • singular。消息中可以包含该字段零次或一次(不超过一次)。在proto3语法中,字段默认使用该规则。
  • repeated:可重复字段
  • 标识号:唯一,范围[0,2^29-1]

定义服务

// 文件服务
service File {
  // rpc 函数名 (传入参数) returns (返回参数) 流
    rpc UploadPlaybook (stream UploadPlaybookRequest) returns (UploadPlaybookResponse) {
        option (google.api.http) = {
            post: "/v1/fi/uplo***ook"
            body: "*"
        };
    }
}

rpc(远程过程调用协议 remote procedure call)和grpc

传输层和应用层之间传输信息

grpc:像调用本地服务一样调用远程服务,基于HTTP2

二者区别:

  • 通信协议 。gRPC是基于HTTP/2的开源RPC框架;RPC可以使用不同的传输协议,例如HTTP、TCP等。
  • 序列化协议 。gRPC使用Google开发的Protocol Buffers作为其默认的序列化协议;RPC可以使用不同的序列化协议,例如XML、JSON等。
  • 平台支持 。gRPC主要支持多种编程语言和平台,包括C++、Java、Python等;RPC可以在各种平台上运行,包括Windows、Linux、Mac等。
  • 性能和效率 。由于使用HTTP/2和Protocol Buffers,gRPC在性能和效率上通常优于传统的RPC

服务端

proto写的协议作为服务端,编译后给客户端调用(方法同名)

// 新建服务端
grpcServer := grpc.NewServer(grpcServerOpts...)
// 注册服务	manager/server/fac_server.go:98
func RegisterWorkOrderFrontServer(s *grpc.Server, srv WorkOrderFrontServer) {
	s.RegisterService(&_WorkOrderFront_serviceDesc, srv)
}

客户端

func (c *Client) getConn(endpoint string, opts ...grpc.DialOption) (conn *grpc.ClientConn) {
	// 兼容tls认证
	if strings.HasSuffix(endpoint, ":端口") {
		creds := credentials.NewTLS(&tls.Config{
			InsecureSkipVerify: true,
		})
		opts = append(opts, grpc.WithTransportCredentials(creds))
	} else {
		opts = append(opts, grpc.WithInsecure())
	}
	var grpcMaxCallSendMsgSize, grpcMaxCallRecvMsgSize int
	if grpcMaxCallSendMsgSize = config.Config().GetInt("配置size") * rpcconst.MB; grpcMaxCallSendMsgSize == 0 {
		grpcMaxCallSendMsgSize = 15 * rpcconst.MB
	}
	if grpcMaxCallRecvMsgSize = config.Config().GetInt("配置size") * rpcconst.MB; grpcMaxCallRecvMsgSize == 0 {
		grpcMaxCallRecvMsgSize = 15 * rpcconst.MB
	}
	log.Debugf("grpc endpoint[%s] MaxCallSendMsgSize[%v], MaxCallRecvMsgSize[%v]", endpoint, grpcMaxCallSendMsgSize, grpcMaxCallRecvMsgSize)
	opts = append(opts, grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(grpcMaxCallSendMsgSize), grpc.MaxCallRecvMsgSize(grpcMaxCallRecvMsgSize)))
	// 新建连接,读取配置
    conn, err := grpc.Dial(endpoint, opts...)
	if err != nil {
		log.Errorf("connect grpc %s error: %s", endpoint, err)
		return
	}
	log.Infof("connect grpc %s success", endpoint)
	c.conns = append(c.conns, conn)
	return conn
}

import使用

// 从当前目录算起
import "common/api.proto";

  • 1
  • 1
  • 0
0 评论
0/1000
评论(0) 发表评论
f****n

f****n

4 篇文章 1 粉丝
关注

go proto3简介

2024-04-25 15:30:46 5阅读

简介

在Go中使用Protocol Buffers的proto3版本,你首先需要定义.proto文件来描述你的消息格式,然后使用protoc编译器来生成Go代码。具有高效自动化解析和生成的能力,同时其压缩比例高,可以节省空间,提高效率。

编译

  • 定义.proto文件
syntax = "proto3";

package example;

// MyMessage is the message type.
message MyMessage {
  string data = 1;
}

使用protoc编译器生成Go代码。假设你已经安装了Protocol Buffers编译器

protoc --go_out=./ --go-grpc_out=. product.proto

这将在当前目录下生成一个message.pb.go文件,该文件包含了你定义的MyMessage消息类型的Go表示。

接下来,在Go代码中你可以使用生成的代码来序列化和反序列化消息:

package main

import (
    "fmt"
    "log"

    "your_project_path/example" // Replace with the actual import path for your generated code
)

func main() {
    // Create a new instance of MyMessage
    message := &example.MyMessage{
        Data: "Hello, Proto3!",
    }

    // Serialize the message to a byte array
    serializedMessage, err := proto.Marshal(message)
    if err != nil {
        log.Fatalf("Failed to serialize message: %v", err)
    }

    fmt.Printf("Serialized message: %x\n", serializedMessage)

    // Deserialize the message from the byte array
    newMessage := &example.MyMessage{}
    if err := proto.Unmarshal(serializedMessage, newMessage); err != nil {
        log.Fatalf("Failed to deserialize message: %v", err)
    }

    fmt.Printf("Deserialized message: %s\n", newMessage.Data)
}

在这个例子中,我们首先创建了一个MyMessage的实例,并使用proto.Marshal函数将其序列化为字节数组。然后,我们使用proto.Unmarshal函数将字节数组反序列化为一个新的MyMessage实例。

确保将your_project_path/example替换为实际生成代码的导入路径。如果你的.proto文件和Go代码不在同一个包中,你可能需要调整导入路径以正确引用生成的代码。

注意,从proto3开始,Go生成的代码不再使用Get和Set方法来访问字段,而是直接使用字段名。此外,proto3不再支持字段的required标记,所有字段都是可选的。如果字段未被设置,其值将是该字段类型的零值

语法

Proto3语法的基本结构由三部分组成,分别是package、message和field。其中,message用于定义消息格式,类似于Java中的类定义。

  • optional:可选 自动变成指针
  • singular。消息中可以包含该字段零次或一次(不超过一次)。在proto3语法中,字段默认使用该规则。
  • repeated:可重复字段
  • 标识号:唯一,范围[0,2^29-1]

定义服务

// 文件服务
service File {
  // rpc 函数名 (传入参数) returns (返回参数) 流
    rpc UploadPlaybook (stream UploadPlaybookRequest) returns (UploadPlaybookResponse) {
        option (google.api.http) = {
            post: "/v1/fi/uplo***ook"
            body: "*"
        };
    }
}

rpc(远程过程调用协议 remote procedure call)和grpc

传输层和应用层之间传输信息

grpc:像调用本地服务一样调用远程服务,基于HTTP2

二者区别:

  • 通信协议 。gRPC是基于HTTP/2的开源RPC框架;RPC可以使用不同的传输协议,例如HTTP、TCP等。
  • 序列化协议 。gRPC使用Google开发的Protocol Buffers作为其默认的序列化协议;RPC可以使用不同的序列化协议,例如XML、JSON等。
  • 平台支持 。gRPC主要支持多种编程语言和平台,包括C++、Java、Python等;RPC可以在各种平台上运行,包括Windows、Linux、Mac等。
  • 性能和效率 。由于使用HTTP/2和Protocol Buffers,gRPC在性能和效率上通常优于传统的RPC

服务端

proto写的协议作为服务端,编译后给客户端调用(方法同名)

// 新建服务端
grpcServer := grpc.NewServer(grpcServerOpts...)
// 注册服务	manager/server/fac_server.go:98
func RegisterWorkOrderFrontServer(s *grpc.Server, srv WorkOrderFrontServer) {
	s.RegisterService(&_WorkOrderFront_serviceDesc, srv)
}

客户端

func (c *Client) getConn(endpoint string, opts ...grpc.DialOption) (conn *grpc.ClientConn) {
	// 兼容tls认证
	if strings.HasSuffix(endpoint, ":端口") {
		creds := credentials.NewTLS(&tls.Config{
			InsecureSkipVerify: true,
		})
		opts = append(opts, grpc.WithTransportCredentials(creds))
	} else {
		opts = append(opts, grpc.WithInsecure())
	}
	var grpcMaxCallSendMsgSize, grpcMaxCallRecvMsgSize int
	if grpcMaxCallSendMsgSize = config.Config().GetInt("配置size") * rpcconst.MB; grpcMaxCallSendMsgSize == 0 {
		grpcMaxCallSendMsgSize = 15 * rpcconst.MB
	}
	if grpcMaxCallRecvMsgSize = config.Config().GetInt("配置size") * rpcconst.MB; grpcMaxCallRecvMsgSize == 0 {
		grpcMaxCallRecvMsgSize = 15 * rpcconst.MB
	}
	log.Debugf("grpc endpoint[%s] MaxCallSendMsgSize[%v], MaxCallRecvMsgSize[%v]", endpoint, grpcMaxCallSendMsgSize, grpcMaxCallRecvMsgSize)
	opts = append(opts, grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(grpcMaxCallSendMsgSize), grpc.MaxCallRecvMsgSize(grpcMaxCallRecvMsgSize)))
	// 新建连接,读取配置
    conn, err := grpc.Dial(endpoint, opts...)
	if err != nil {
		log.Errorf("connect grpc %s error: %s", endpoint, err)
		return
	}
	log.Infof("connect grpc %s success", endpoint)
	c.conns = append(c.conns, conn)
	return conn
}

import使用

// 从当前目录算起
import "common/api.proto";

文章来自专栏

心得

4 篇文章 1 订阅
0 评论
0/1000
评论(0) 发表评论
  • 1
    点赞
  • 1
    收藏
  • 0
    评论