本文小编为大家详细介绍“Golang怎么使用gob实现结构体的序列化”,内容详细,步骤清晰,细节处理妥当,希望这篇“Golang怎么使用gob实现结构体的序列化”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
Golang有自己的序列化格式,称为gob。使用gob可以对结构进行编码和解码。你可以使用其他格式,如JSON, XML, protobuff等,具体选择要根据实际需求,但当接收和发送都为Golang,我建议使用Go的gob格式。
Gob简介
gob在kg/encoding/gob包中:
gob流是自描述的,这意味着我们不需要创建单独的文件来解释(使用protobuff格式需要创建文件)
gob流中的每个数据项之前都有其类型说明(一些预定义的类型)
Gob包很简单,仅包括8个函数和5个类型:
func Register(value interface{})func RegisterName(name string, value interface{})type CommonTypetype Decoderfunc NewDecoder(r io.Reader) *Decoderfunc (dec *Decoder) Decode(e interface{}) errorfunc (dec *Decoder) DecodeValue(v reflect.Value) errortype Encoderfunc NewEncoder(w io.Writer) *Encoderfunc (enc *Encoder) Encode(e interface{}) errorfunc (enc *Encoder) EncodeValue(value reflect.Value) errortype GobDecodertype GobEncoder
单个对象序列化
首先定义student结构体,包括两个字段Name和Age.
使用gob.NewEncoder和gob.NewDecoder方法,接收io.Writer 和 io.Reader 对象,用于读写文件:
package mainimport ( "fmt" "os" "encoding/gob")type Student struct { Name string Age int32}func main() { fmt.Println("Gob Example") student := Student{"Ketan Parmar",35} err := writeGob("./student.gob",student) if err != nil{ fmt.Println(err) } var studentRead = new (Student) err = readGob("./student.gob",studentRead) if err != nil { fmt.Println(err) } else { fmt.Println(studentRead.Name, "\t", studentRead.Age) }}func writeGob(filePath string,object interface{}) error { file, err := os.Create(filePath) if err == nil { encoder := gob.NewEncoder(file) encoder.Encode(object) } file.Close() return err}func readGob(filePath string,object interface{}) error { file, err := os.Open(filePath) if err == nil { decoder := gob.NewDecoder(file) err = decoder.Decode(object) } file.Close() return err}
列表数据序列化
首先创建student结构体数组或slice,然后填充数据。下面示例无需修改readGob和writeGob函数:
package mainimport ( "fmt" "os" "encoding/gob")type Student struct { Name string Age int32}type Students []Studentfunc main() { fmt.Println("Gob Example") students := Students{} students = append(students,Student{"Student 1",20}) students = append(students,Student{"Student 2",25}) students = append(students,Student{"Student 3",30}) err := writeGob("./student.gob",students) if err != nil{ fmt.Println(err) } var studentRead = new (Students) err = readGob("./student.gob",studentRead) if err != nil { fmt.Println(err) } else { for _,v := range *studentRead{ fmt.Println(v.Name, "\t", v.Age) } }}
上面两个示例主要使用了NewEncoder 和 NewDecoder,接下来看看其他函数:Register, Encode, EncodeValue, Decode 和 DecodeValue。
Encode 和 Decode 函数主要用于网络应用程序,方法签名如下:
func (dec *Decoder) Decode(e interface{}) error
func (enc *Encoder) Encode(e interface{}) error
简单编码示例
package mainimport ( "fmt" "encoding/gob" "bytes")type Student struct { Name string Age int32}func main() { fmt.Println("Gob Example") studentEncode := Student{Name:"Ketan",Age:30} var b bytes.Buffer e := gob.NewEncoder(&b) if err := e.Encode(studentEncode); err != nil { panic(err) } fmt.Println("Encoded Struct ", b) var studentDecode Student d := gob.NewDecoder(&b) if err := d.Decode(&studentDecode); err != nil { panic(err) } fmt.Println("Decoded Struct ", studentDecode.Name,"\t",studentDecode.Age)}
上面示例把student结构序列化、反序列化。序列化后存储在字节buffer变量b中,先可以使用b在网络中传输。要解码仅需要创建相同结构对象并提供其地址。studentDecode变量获得解码的内容。
编码在TCP连接中使用
TCP客户端:打开连接使用gob.Encoder方法编码数据进行传输:
package mainimport ( "fmt" "encoding/gob" "net" "log")type Student struct { Name string Age int32}func main() { fmt.Println("Client") //create structure object studentEncode := Student{Name:"Ketan",Age:30} fmt.Println("start client"); // dial TCP connection conn, err := net.Dial("tcp", "localhost:8080") if err != nil { log.Fatal("Connection error", err) } //Create encoder object, We are passing connection object in Encoder encoder := gob.NewEncoder(conn) // Encode Structure, IT will pass student object over TCP connection encoder.Encode(studentEncode) // close connection conn.Close() fmt.Println("done");}
TCP Server: 监听8080端口,在go协程中处理所有客户端,使用gob.Decoder方法解码student结构体并输出:
package mainimport ( "fmt" "net" "encoding/gob")type Student struct { Name string Age int32}func handleConnection(conn net.Conn) { // create new decoder object and provide connection dec := gob.NewDecoder(conn) // create blank student object p := &Student{} // decode serialize data dec.Decode(p) // print fmt.Println("Hello ",p.Name,", Your Age is ",p.Age); // close connection for that client conn.Close()}func main() { fmt.Println("Server") // start TCP server and listen on port 8080 ln, err := net.Listen("tcp", ":8080") if err != nil { // handle error panic(err) } for { // this blocks until connection or error conn, err := ln.Accept() if err != nil { // handle error continue } // a goroutine handles conn so that the loop can accept other connections go handleConnection(conn) }}
上文中没有实现序列化,本文给出golang-ttl-map实现:
func (h *Heap) append(data Data) (err error) {h.fileMx.Lock()defer h.fileMx.Unlock() // 打开文件var file *os.Filefile, err = os.OpenFile(h.filePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0755)if err != nil {return}defer func() {_ = file.Sync()}()defer func() {_ = file.Close()}() // 定义buffervar buf bytes.Bufferenc := gob.NewEncoder(&buf) // 序列化err = enc.Encode(data)if err != nil {return}bs := buf.Bytes()bs = append(bs, '\n') // 写入文件_, err = file.Write(bs)if err != nil {return}return}
读到这里,这篇“Golang怎么使用gob实现结构体的序列化”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。