序列化结构数据方法ProtoBuf使用(PHP和Go)

一、在PHP下使用ProtoBuf
 
PHP如果要使用protobuf 需要安装 protoc+ 安装protobuf composer包
 
  • protoc用于根据protobuf数据结构文件(.proto)生成对应的类,用于生成protobuf文件
  • 安装 google/protobuf composer 包composer require google/protobuf

 
怎么用呢?开搞!
 
1、首先,需要定一个消息类型。创建一个关于Person的定义文件(以.proto为后缀),如示例为person.proto,文件内容如下:
syntax="proto3";
package test;
message Person{
string name=1;//姓名
int32 age=2;//年龄
bool sex=3;//性别
}
 
  1. syntax="proto3":表明使用的是proto3格式,如果不指定则为proto2
  2. package test:定义包名为test,生成类时,会产生一个目录为test
  3. message Person:消息主体内容,里面为各个字段的定义

 
2、生成对应的PHP类
 
定义好Person的格式后,该格式如果不生成我们所需要的类库,其实是无任何意义的,还google提供一个工具protoc生成我们要的类库。也就是最开始说的 protoc!
 
proto 最新版的下载地址是:最新3.11.3。可以通过 官方包Release 进行有选择的下载。
tar -zxvf protobuf-php-3.11.3.tar.gz
cd protobuf-3.11.3
./configure --prefix=/usr/local/protobuf
make
make install
解压安装完后,就可以通过下面的命令,生成对应的类库了:
/usr/
local/protobuf/bin/protoc --php_out=./ person.proto
生成后将在当前目录产生如下文件:
 
  • GPBMetadata/Person.php
  • Test/Person.php

 
3、类库生成完了,就可以在PHP项目中使用ProtoBuf了:

在PHP中使用ProtoBuf依赖一个protobuf的扩展,目前提供两种方式进行使用: 
  1. php的c扩展,
  2. php的lib扩展包,

 
这两者均可在刚才下载包里可以找到。
 
另外,也可以使用composer进行安装该依赖扩展:
composer require google/protobuf

这里我主要是使用composer安装,应该它可以帮我产生autoload。安装好依赖后,我们就可以开始在php环境下使用protobuf了。

序列化
<?php
include 'vendor/autoload.php';
include 'GPBMetadata/Person.php';
include 'Test/Person.php';
$bindata = file_get_contents('./data.bin');
$person = new Test\Person();
$person->mergeFromString($bindata);
echo $person->getName();
运行后,产生的data.bin,只有14Byte
 
反序列化
<?php
include 'vendor/autoload.php';
include 'GPBMetadata/Person.php';
include 'Test/Person.php';
$bindata = file_get_contents('./data.bin');
$person = new Test\Person();
$person->mergeFromString($bindata);
echo $person->getName();
PHP常用的使用方法:

序列化:
1、serializeToString:序列化成二进制字符串
2、serializeToJsonString:序列化成JSON字符串

反序列化:
1、mergeFromString:二进制字符串反序列化
2、mergeFromJsonString:Json字符串反序列化

二、在Golang下使用ProtoBuf
 
安装protoc的方法和PHP中类型,编译安装即可。
 
安装好之后,需要安装ProtoBuf的编译器插件:protoc-gen-go:
 
进入GOPATH目录,运行:
go get -u github.com/golang/protobuf/protoc-gen-go
  如果成功,会在GOPATH/bin下生成protoc-gen-go.exe文件(Windows上)。
 
1、准备好之后,就可以开始写proto文件了。假设文件目录为:
$GOPATH/src/test/protobuf/pb/user.proto
代码如下:
//指定版本
//注意proto3与proto2的写法有些不同
syntax = "proto3";

//包名,通过protoc生成时go文件时
package test;

//手机类型
//枚举类型第一个字段必须为0
enum PhoneType {
HOME = 0;
WORK = 1;
}

//手机
message Phone {
PhoneType type = 1;
string number = 2;
}

//人
message Person {
//后面的数字表示标识号
int32 id = 1;
string name = 2;
//repeated表示可重复
//可以有多个手机
repeated Phone phones = 3;
}

//联系簿
message ContactBook {
repeated Person persons = 1;
}
然后运行如下命令:
 protoc --go_out=. *.proto
会生成一个user.pb.go的文件。
 
2、使用:
package main;

import (
"github.com/golang/protobuf/proto"
"go_dev/kongji/proto/test"
"io/ioutil"
"os"
"fmt"
)

func write() {
p1 := &test.Person{
Id: 1,
Name: "小张",
Phones: []*test.Phone{
{test.PhoneType_HOME, "111111111"},
{test.PhoneType_WORK, "222222222"},
},
};
p2 := &test.Person{
Id: 2,
Name: "小王",
Phones: []*test.Phone{
{test.PhoneType_HOME, "333333333"},
{test.PhoneType_WORK, "444444444"},
},
};

//创建地址簿
book := &test.ContactBook{};
book.Persons = append(book.Persons, p1);
book.Persons = append(book.Persons, p2);

//编码数据
data, _ := proto.Marshal(book);
//把数据写入文件
ioutil.WriteFile("./test.txt", data, os.ModePerm);
}

func read() {
//读取文件数据
data, _ := ioutil.ReadFile("./test.txt");
book := &test.ContactBook{};
//解码数据
proto.Unmarshal(data, book);
for _, v := range book.Persons {
fmt.Println(v.Id, v.Name);
for _, vv := range v.Phones {
fmt.Println(vv.Type, vv.Number);
}
}
}

func main() {
write();
read();
}

 

内容整理自下面链接:
https://www.jianshu.com/p/ce098058edf0
https://developers.google.cn/protocol-buffers/docs/gotutorial
https://developers.google.cn/protocol-buffers/docs/reference/go-generated
 

0 个评论

要回复文章请先登录注册