go实践十六 使用protobuf读写文件

为什么要使用protobuf

最近的项目中,一直使用Json做数据传输。Json用起来的确很方便。但相对于protobuf数据量更大些。做一个移动端应用,为用户省点流量还是很有必要的。正好也可以学习一下protobuf的使用

跟Json相比protobuf性能更高,更加规范

  • 编解码速度快,数据体积小
  • 使用统一的规范,不用再担心大小写不同导致解析失败等蛋疼的问题了

但也失去了一些便利性

  • 改动协议字段,需要重新生成文件。
  • 数据没有可读性

protobuf github: https://github.com/protocolbuffers/protobuf/releases

本文使用的是 https://github.com/protocolbuffers/protobuf/releases/download/v3.9.0/protobuf-all-3.9.0.tar.gz

下载到linux中,编译安装

# 下载安装包
[root@izj6c4jirdug8kh3uo6rdez package]# wget https://github.com/protocolbuffers/protobuf/releases/download/v3.9.0/protobuf-all-3.9.0.tar.gz

# 解压
[root@izj6c4jirdug8kh3uo6rdez package]# tar -zxvf proto*

# 切换到解压后的目录
[root@izj6c4jirdug8kh3uo6rdez protobuf-3.9.0]# cd proto*

# 设置安装目录
[root@izj6c4jirdug8kh3uo6rdez protobuf-3.9.0]# ./configure --prefix=/usr/local/proto

# 编译安装
[root@izj6c4jirdug8kh3uo6rdez protobuf-3.9.0]# make && make install

# 添加到bin目录
[root@izj6c4jirdug8kh3uo6rdez protobuf-3.9.0]# ln -s /usr/local/proto/bin/protoc /usr/bin/protoc

# 查看版本
[root@izj6c4jirdug8kh3uo6rdez protobuf-3.9.0]# protoc --version
libprotoc 3.9.0


安装goprotobuf

# protoc-gen-go是用来将protobuf的的代码转换成go语言代码的一个插件
[root@izj6c4jirdug8kh3uo6rdez protobufffile]# go get -u github.com/golang/protobuf/protoc-gen-go

# proto是protobuf在golang中的接口模块
[root@izj6c4jirdug8kh3uo6rdez protobufffile]# go get -u github.com/golang/protobuf/proto


# 设置 protoc-gen-go 命令

[root@izj6c4jirdug8kh3uo6rdez protobufffile]# find / -name protoc-gen-go
/usr/local/go/gopath/bin/protoc-gen-go
/usr/local/go/gopath/pkg/mod/github.com/golang/protobuf@v1.3.2/protoc-gen-go
/usr/local/go/gopath/pkg/mod/github.com/golang/protobuf@v1.3.1/protoc-gen-go

[root@izj6c4jirdug8kh3uo6rdez protobufffile]# ln -s /usr/local/go/gopath/bin/protoc-gen-go /usr/bin/protoc-gen-go

目录结构如下: 
项目根目录是 protobufffile

protobufffile的目录结构
├── protobuf                        # proto文件统一存放目录
│   ├── protobuf.proto          # proto文件
├── main.go                         # 项目单入口              

下面,我们根据目录结构,从上往下建立文件夹和文件

建立文件夹和文件 protobufffile/protobuf/protobuf.proto ,protobuf.proto 内容如下:

//指定版本
//注意proto3与proto2的写法有些不同
syntax = "proto3";
//包名,通过protoc生成时go文件时
package protobuf;

//声明一个消息体描述一个请求或者响应的消息格式
message HelloWorld {
    int32 id = 1;
    string name = 2;
    int32 sin = 3;
}

建立文件 protobufffile/main.go ,main.go 内容如下:

package main

import (
	"fmt"
	"os"
	"io"

	"github.com/golang/protobuf/proto"

	stProto "protobufffile/protobuf"
)

func main() {
	//写入数据
	protobuffWrite()
	//读取数据
	protobuffRead()
}

func protobuffWrite(){

	//初始化protobuf数据格式
	msg := &stProto.HelloWorld{
		Id:     *proto.Int32(17),
		Name:   *proto.String("hello world"),
		Sin:    *proto.Int32(18),

	}

	filename := "./protobufffile.txt"
	fmt.Printf("使用protobuf创建文件 %s\n",filename)
	fObj,_ := os.Create(filename)  //创建文件
	defer fObj.Close() //关闭文件 ,defer 会在程序最后运行
	buffer,_ := proto.Marshal(msg)  //序列化数据
	fObj.Write(buffer) //写入文件
}

func protobuffRead(){
	filename := "protobufffile.txt"
	file,fileErr := os.Open(filename)  //打开文件
	checkError(fileErr)

	defer file.Close()//关闭文件 ,defer 会在程序最后运行
	fs,fsErr := file.Stat()
	checkError(fsErr)
	buffer := make([]byte,fs.Size()) //创建 byte切片
	//把file文件内容读取到buffer
	_,readErr := io.ReadFull(file,buffer)
	checkError(readErr)

	//初始化pb结构体对象并将buffer中的文件内容读取到pb结构体中
	msg := &stProto.HelloWorld{}
	pbErr := proto.Unmarshal(buffer, msg) //反序列化数据
	checkError(pbErr)
	fmt.Printf("读取文件:%s \r\nname:%s\nid:%d\nopt:%d\n",filename,msg.GetName(),msg.GetId(),msg.GetSin())
}

//检查错误
func checkError(err error) {
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(-1)
	}
}

切换到protobufffile/protobuf目录中,编译 .proto 文件,生成 Go 语言文件

[root@izj6c4jirdug8kh3uo6rdez protobufffile]# cd protobuf

[root@izj6c4jirdug8kh3uo6rdez protobuf]# ll
total 4
-rw-r--r-- 1 root root 302 Aug  6 12:37 protobuf.proto

[root@izj6c4jirdug8kh3uo6rdez protobuf]# protoc --go_out=. *.proto

[root@izj6c4jirdug8kh3uo6rdez protobuf]# ll
total 8
-rw-r--r-- 1 root root 3186 Aug  6 12:38 protobuf.pb.go
-rw-r--r-- 1 root root  302 Aug  6 12:37 protobuf.proto

切换到protobufffile目录中, 初始化包

[root@izj6c4jirdug8kh3uo6rdez protobufffile]# go mod init protobufffile
go: creating new go.mod: module protobufffile

打包项目

[root@izj6c4jirdug8kh3uo6rdez protobufffile]# go build

运行

[root@izj6c4jirdug8kh3uo6rdez protobufffile]# ./protobufffile
使用protobuf创建文件 ./protobufffile.txt
读取文件:protobufffile.txt 
name:hello world
id:17
opt:18

参考:https://www.jianshu.com/p/f4051569fd32

参考:https://segmentfault.com/a/1190000009277748

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
安装protobuf 1. 下载protobuf编译器:https://github.com/protocolbuffers/protobuf/releases 2. 安装protobuf编译器: ``` $ tar -xzvf protobuf-3.15.6.tar.gz $ cd protobuf-3.15.6/ $ ./configure $ make $ sudo make install $ sudo ldconfig ``` 3. 安装protobuf的Go语言支持: ``` $ go get github.com/golang/protobuf/protoc-gen-go ``` 该命令会从GitHub上下载并编译出protoc-gen-go可执行文件,该文件是一个protobuf插件,用于将proto文件生成Go语言代码。 使用protobuf 1. 编写proto文件 ```protobuf syntax = "proto3"; package example; message Person { string name = 1; int32 age = 2; repeated string hobbies = 3; } ``` 2. 使用protoc命令生成Go语言代码 ``` $ protoc --go_out=. example.proto ``` 该命令会在当前目录下生成example.pb.go文件,其中包含了protobuf定义的Person类型的Go语言结构体。 3. 在Go语言程序中使用protobuf ```go package main import ( "fmt" "example" "github.com/golang/protobuf/proto" ) func main() { p := &example.Person{ Name: "Alice", Age: 20, Hobbies: []string{"swimming", "reading"}, } data, err := proto.Marshal(p) if err != nil { fmt.Println("marshal error:", err) return } p2 := &example.Person{} err = proto.Unmarshal(data, p2) if err != nil { fmt.Println("unmarshal error:", err) return } fmt.Println("p2:", p2) } ``` 该程序使用protobuf将一个Person对象编码为二进制数据,然后解码成另一个Person对象。注意,该程序需要引入github.com/golang/protobuf/proto包,该包提供了protobuf的Go语言支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值