Golang使用gob實現(xiàn)結(jié)構(gòu)體的序列化過程詳解
Golang有自己的序列化格式,稱為gob。使用gob可以對結(jié)構(gòu)進(jìn)行編碼和解碼。你可以使用其他格式,如JSON, XML, protobuff等,具體選擇要根據(jù)實際需求,但當(dāng)接收和發(fā)送都為Golang,我建議使用Go的gob格式。
Gob簡介
gob在kg/encoding/gob包中:
- gob流是自描述的,這意味著我們不需要創(chuàng)建單獨(dú)的文件來解釋(使用protobuff格式需要創(chuàng)建文件)
- gob流中的每個數(shù)據(jù)項之前都有其類型說明(一些預(yù)定義的類型)
Gob包很簡單,僅包括8個函數(shù)和5個類型:
func Register(value interface{}) func RegisterName(name string, value interface{}) type CommonType type Decoder func NewDecoder(r io.Reader) *Decoder func (dec *Decoder) Decode(e interface{}) error func (dec *Decoder) DecodeValue(v reflect.Value) error type Encoder func NewEncoder(w io.Writer) *Encoder func (enc *Encoder) Encode(e interface{}) error func (enc *Encoder) EncodeValue(value reflect.Value) error type GobDecoder type GobEncoder
單個對象序列化
首先定義student結(jié)構(gòu)體,包括兩個字段Name和Age.
使用gob.NewEncoder和gob.NewDecoder方法,接收io.Writer 和 io.Reader 對象,用于讀寫文件:
package main import ( "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 }
列表數(shù)據(jù)序列化
首先創(chuàng)建student結(jié)構(gòu)體數(shù)組或slice,然后填充數(shù)據(jù)。下面示例無需修改readGob和writeGob函數(shù):
package main import ( "fmt" "os" "encoding/gob" ) type Student struct { Name string Age int32 } type Students []Student func 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,接下來看看其他函數(shù):Register, Encode, EncodeValue, Decode 和 DecodeValue。
Encode 和 Decode 函數(shù)主要用于網(wǎng)絡(luò)應(yīng)用程序,方法簽名如下:
func (dec *Decoder) Decode(e interface{}) error
func (enc *Encoder) Encode(e interface{}) error
簡單編碼示例
package main import ( "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結(jié)構(gòu)序列化、反序列化。序列化后存儲在字節(jié)buffer變量b中,先可以使用b在網(wǎng)絡(luò)中傳輸。要解碼僅需要創(chuàng)建相同結(jié)構(gòu)對象并提供其地址。studentDecode變量獲得解碼的內(nèi)容。
編碼在TCP連接中使用
TCP客戶端:打開連接使用gob.Encoder方法編碼數(shù)據(jù)進(jìn)行傳輸:
package main import ( "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: 監(jiān)聽8080端口,在go協(xié)程中處理所有客戶端,使用gob.Decoder方法解碼student結(jié)構(gòu)體并輸出:
package main import ( "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) } }
上文中沒有實現(xiàn)序列化,本文給出golang-ttl-map實現(xiàn):
func (h *Heap) append(data Data) (err error) { h.fileMx.Lock() defer h.fileMx.Unlock() // 打開文件 var file *os.File file, 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() }() // 定義buffer var buf bytes.Buffer enc := 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 }
到此這篇關(guān)于Golang使用gob實現(xiàn)結(jié)構(gòu)體的序列化過程詳解的文章就介紹到這了,更多相關(guān)Golang結(jié)構(gòu)體序列化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go?runtime?調(diào)度器之系統(tǒng)調(diào)用引起的搶占
本文解析了在Go語言中,當(dāng)goroutine執(zhí)行的系統(tǒng)調(diào)用時間過長時,系統(tǒng)如何通過監(jiān)控和搶占機(jī)制來處理,以維持運(yùn)行效率和資源分配的平衡,通過具體的示例和流程圖,詳細(xì)展示了系統(tǒng)調(diào)用過程中的搶占操作,感興趣的朋友跟隨小編一起看看吧2024-09-09Golang 模塊引入及表格讀寫業(yè)務(wù)快速實現(xiàn)示例
這篇文章主要為大家介紹了Golang模塊引入及表格讀寫業(yè)務(wù)的快速實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07golang 40行代碼實現(xiàn)通用協(xié)程池
golang協(xié)程機(jī)制很方便的解決了并發(fā)編程的問題,但是協(xié)程并不是沒有開銷的,所以也需要適當(dāng)限制一下數(shù)量。這篇文章主要介紹了golang 40行代碼實現(xiàn)通用協(xié)程池,需要的朋友可以參考下2018-08-08Go語言中init函數(shù)和defer延遲調(diào)用關(guān)鍵詞詳解
這篇文章主要介紹了Go語言中init函數(shù)和defer延遲調(diào)用關(guān)鍵詞,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03一文教你如何快速學(xué)會Go的切片和數(shù)組數(shù)據(jù)類型
數(shù)組是屬于同一類型的元素的集合。切片是數(shù)組頂部的方便、靈活且功能強(qiáng)大的包裝器。本文就來和大家聊聊Go中切片和數(shù)組的使用,需要的可以參考一下2023-03-03