一、基本概念
1.什么是序列化/反序列化
把对象转换为字节序列的过程称为对象的序列化;
把字节序列恢复为对象的过程称为对象的反序列化。
2.序列化的作用
(1)把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中
(2)在网络上传送对象的字节序列。
在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。
3.序列化的方式
(1)json序列化
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
Name string
Age uint8
Address string
}
func main() {
s := Student{
"stephen",
18,
"henan",
}
data, err := json.Marshal(s)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%s\n", string(data))
var stu Student
json.Unmarshal(data, &stu)
fmt.Println(" haha", stu)
}
(2)protobuff序列化
(3)binary序列化
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
type Student struct {
Name string
Age uint8
}
func (stu *Student) Marshal() ([]byte, error) {
// 创建一个缓冲器,缓冲的类型是byte
buff := bytes.NewBuffer(make([]byte, 0))
// 也可以这样创建
// buff := new(bytes.Buffer)
if err := binary.Write(buff, binary.BigEndian, &stu.Age); err != nil {
return nil, err
}
buff.Write([]byte(stu.Name))
return buff.Bytes(), nil
}
func (stu *Student) Unmarshal(k []byte) (err error) {
// 创建一个缓冲器,缓冲的类型是byte
buff := bytes.NewBuffer(k)
if err = binary.Read(buff, binary.BigEndian, &stu.Age); err != nil {
return
}
stu.Name = string(buff.Bytes())
return
}
func main() {
s := Student{
"stephen",
18,
}
data, err := s.Marshal()
if err != nil {
fmt.Println(err)
return
}
var stu Student
stu.Unmarshal(data)
fmt.Println("haha", stu)
}
二、实际使用
遇到一个问题,编译可以,运行报错,binary.Write: invalid type *string,如果换成string,则报错binary.Write: invalid type string
定位到的出错代码:
buff := bytes.NewBuffer(make([]byte, 0, 128))
if err := binary.Write(buff, binary.BigEndian, &lk.Ino); err != nil {
panic(err)
}
if err = binary.Write(buff, binary.BigEndian, &lk.Name); err != nil {
panic(err)
}
原因是string是不确定大小的类型,binary会报错,并且不可以序列化string的指针
解决方法是序列化string内容:
buff.Write([]byte(lk.Name))
反序列化时:
lk.Name = string(buff.Bytes())
Reference:
[1] http://www.pangxieke.com/go/go-serialize.html