搜尋
首頁後端開發Golanggolang序列化方法有哪些

golang序列化方法有哪些

Jan 04, 2023 pm 07:33 PM
golanggo語言序列化

golang序列化方法有:1、利用Gob套件管理gob流,gob是和型別綁定的,如果發現多了或少了,會依據順序填入或截斷。 2.利用json包,能實現RFC 7159中定義的JSON編碼和解碼;在序列化的過程中,如果結構體內的成員是小寫的,則會出現錯誤。 3.利用Binary包,能實現數字和位元組序列之間的簡單轉換以及varint的編碼和解碼。 4.利用protobuf協議。

golang序列化方法有哪些

本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。

在程式設計過程中,我們總是要遇到這樣的問題,就是將我們的資料物件要在網路中傳輸或儲存到文件,這就需要對其編碼和解碼動作。

目前存在著許多編碼格式:json, XML, Gob, Google Protocol Buffer 等,在Go 語言中,如何對資料進行這樣的編碼和解碼呢?

序列化和反序列化定義

#序列化(Serialization)是將物件的狀態資訊轉換為可以儲存或傳輸的形式的過程。在序列化期間,物件將其目前狀態寫入到臨時或持久性儲存區。

反過來,把變數從從儲存區重新讀取,重新建立該對象,則為反序列化。

在Go語言中,encoding 套件就是專門來處理這類序列化的編碼和解碼的問題。

序列化方式–Gob

#gob 套件管理gob 串流–編碼器(傳送器)和解碼器(接收器)之間交換的二進位值。一個典型的用途是傳輸遠端過程呼叫(RPCs)的參數和結果,如 "net/rpc "套件中就使用了gobs 流。

具體可以參考文件:https://docs.studygolang.com/pkg/encoding/gob/

他的官網給了一個範例:

package main

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"log"
)

type P struct {
	X, Y, Z int
	Name    string
}

type Q struct {
	X, Y *int32
	Name string
}

// This example shows the basic usage of the package: Create an encoder,
// transmit some values, receive them with a decoder.
func main() {
	// Initialize the encoder and decoder. Normally enc and dec would be
	// bound to network connections and the encoder and decoder would
	// run in different processes.
	var network bytes.Buffer        // Stand-in for a network connection  //Buffer是具有Read和Write方法的可变大小的字节缓冲区。
	enc := gob.NewEncoder(&network) // Will write to network.
	dec := gob.NewDecoder(&network) // Will read from network.

	// Encode (send) some values.
	err := enc.Encode(P{3, 4, 5, "Pythagoras"})
	if err != nil {
		log.Fatal("encode error:", err)
	}
	err = enc.Encode(P{1782, 1841, 1922, "Treehouse"})
	if err != nil {
		log.Fatal("encode error:", err)
	}

	// Decode (receive) and print the values.
	var q Q
	err = dec.Decode(&q)
	if err != nil {
		log.Fatal("decode error 1:", err)
	}
	fmt.Printf("%q: {%d, %d}\n", q.Name, *q.X, *q.Y)
	err = dec.Decode(&q)
	if err != nil {
		log.Fatal("decode error 2:", err)
	}
	fmt.Printf("%q: {%d, %d}\n", q.Name, *q.X, *q.Y)

}

運行結果是:

"Pythagoras": {3, 4}
"Treehouse": {1782, 1841}

個人認為這個例子是真的好。我們看到,結構體PQ 是不同的,我們看到Q 少了一個 Z 變數。

但是,在解碼的時候,仍然能解析得出來,這說明,使用gob 時,是根據類型綁定的,如果發現多了或者少了,會依據順序填充或截斷。

接下來,我們詳情說說怎麼編碼吧:

1. bytes.Buffer 類型

首先,我們需要定義一個bytes.Buffer 類型,用來承接需要序列化的結構體,這個類型是這樣的:

// A Buffer is a variable-sized buffer of bytes with Read and Write methods.(Buffer是具有Read和Write方法的可变大小的字节缓冲区)
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
	buf      []byte // contents are the bytes buf[off : len(buf)]
	off      int    // read at &buf[off], write at &buf[len(buf)]
	lastRead readOp // last read operation, so that Unread* can work correctly.
}

使用上面的例子,可以看到輸出是:

"Pythagoras": {3, 4} ==>
{[42 255 129 3 1 1 1 80 1 255 130 0 1 4 1 1 88 1 4 0 1 1 89 1 4 0 1 1 90 1 4 0 1 4 78 97 109 101 1 12 0 0 0 21 255 130 1 6 1 8 1 10 1 10 80 121 116 104 97 103 111 114 97 115 0] 0 0}

可以看到,Buffer 裡,是二進位數(一個位元組8個bit,最高255)

2. Encode 編碼

之後,對需要編碼序列化的結構體進行編碼:

enc := gob.NewEncoder(&network) // Will write to network.
// Encode (send) some values.
if err := enc.Encode(P{3, 4, 5, "Pythagoras"}); err != nil {
	log.Fatal("encode error:", err)
}

這裡,首先是要獲得*Encoder對象,取得對象後,利用*Encoder 物件的方法Encode 進行編碼。

這裡,需要注意的是,Encode 如果是網路程式設計的,其實是可以直接傳送訊息給對方的,而不必進行 socket 的send 操作。

例如:在srever 端有程式碼:

func main() {
	l, err := net.Listen("tcp", "127.0.0.1:8000")  //监听端口
	if err != nil {
		log.Fatal("net Listen() error is ", err)
	}

	p := P{
		1, 2, 3,
		"name"}

	conn, err := l.Accept()
	if err != nil {
		log.Fatal("net Accept() error is ", err)
	}
	defer func() { _ = conn.Close() }()
	//参数是conn 时,即可发出
	enc := gob.NewEncoder(conn)
	if err = enc.Encode(p); err != nil {  //发生结构体数据
		log.Fatal("enc Encode() error is ", err)
	}
}

在客戶端client有:

func main() {
	conn,err := net.Dial("tcp","127.0.0.1:8000")
	if err != nil {
		log.Fatal("net Dial() error is ", err)
	}
	defer func() { _ = conn.Close() }()
	/**
	type Q struct {
		X, Y int
		Name string
	}
	 */
	var q Q
	dec := gob.NewDecoder(conn)
	if err = dec.Decode(&q); err != nil {
		log.Fatal("enc Encode() error is ", err)
	}
	fmt.Println(q)
}

輸出:

{1 2 name}

3. Decode 解碼

最後,對其解碼的步驟為:

dec := gob.NewDecoder(&network) // Will read from network.
if err = dec.Decode(&q);err != nil {
	log.Fatal("decode error 2:", err)
}

序列化方式–json

json 套件實作了RFC 7159 中定義的JSON 編碼和解碼。 JSON和Go值之間的映射在 Marshal 和 Unmarshal 函數的文檔中進行了描述。

有關此程式包的介紹,請參閱「 JSON與Go」:https://www.php.cn/link/241200d15bc67211b50bd10815259e58json/

範例如下:

type Message struct {
	QQ      string
	Address string
}

type Student struct {
	Id   uint64 `json:"id"` //可以保证json字段按照规定的字段转义,而不是输出 Id
	Age  uint64 `json:"age"`
	Data []Message
}

func main() {
	m1 := Message{QQ: "123", Address: "beijing"}
	m2 := Message{QQ: "456", Address: "beijing"}
	s1 := Student{3, 19, append([]Message{}, m1, m2)}
	var buf []byte
	var err error

	if buf, err = json.Marshal(s1); err != nil {
		log.Fatal("json marshal error:", err)
	}

	fmt.Println(string(buf))

	var s2 Student
	if err = json.Unmarshal(buf, &s2); err != nil {
		log.Fatal("json unmarshal error:", err)
	}
	fmt.Println(s2)
}
//输出:
//{"id":3,"age":19,"Data":[{"QQ":"123","Address":"beijing"},{"QQ":"456","Address":"beijing"}]}
//{3 19 [{123 beijing} {456 beijing}]}

#注意

在序列化的過程中,如果結構體內的成員是小寫的,則會出現錯誤。 以上兩種方式,都會出現這樣的結果

我們以json 序列化為例子,看一下如果是小寫的話,會出現什麼樣的結果:

package main

import (
	"encoding/json"
	"fmt"
	"log"
)

type Message struct {
	qq      string
	address string
}

type Student struct {
	Id   uint64 `json:"id"` //可以保证json字段按照规定的字段转义,而不是输出 Id
	Age  uint64 `json:"age"`
	Data []Message
}

func main() {
	m1 := Message{"123", "beijing"}
	m2 := Message{"456", "beijing"}
	s1 := Student{3, 19, append([]Message{}, m1, m2)}
	var buf []byte
	var err error

	if buf, err = json.Marshal(s1); err != nil {
		log.Fatal("json marshal error:", err)
	}

	fmt.Println(string(buf))

	var s2 Student
	if err = json.Unmarshal(buf, &s2); err != nil {
		log.Fatal("json unmarshal error:", err)
	}
	fmt.Println(s2)
}

輸出:

{"id":3,"age":19,"Data":[{},{}]}
{3 19 [{ } { }]}

我們看到,小寫的部分將不會被序列化到,也就是說,會是空值。

這個雖然不會報錯,但很明顯,不是我們想要看到的結果。

報錯:gob: type xxx has no exported fields

我們來看一個會報錯的例子:

type Message struct {
	qq      string
	address string
}

type Student struct {
	Id   uint64 `json:"id"` //可以保证json字段按照规定的字段转义,而不是输出 Id
	Age  uint64 `json:"age"`
	Data []Message
}

func main() {
	m1 := Message{"123", "beijing"}
	m2 := Message{"456", "beijing"}
	s1 := Student{3, 19, append([]Message{}, m1, m2)}

	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	if err := enc.Encode(s1); err != nil {
		log.Fatal("encode error:", err) //报错
	}
	fmt.Println(string(buf.Bytes()))
}

這段程式碼會報錯:

2020/12/30 16:44:47 encode error:gob: type main.Message has no exported fields

提醒我們注意,結構體的大小寫是很敏感的! ! !

序列化方式–Binary

Binary 包实现 数字字节 序列之间的简单转换以及varint的编码和解码。

通过读取和写入固定大小的值来转换数字。 固定大小的值可以是固定大小的算术类型(bool,int8,uint8,int16,float32,complex64等),也可以是仅包含固定大小值的数组或结构体。详情可参考:https://www.php.cn/link/241200d15bc67211b50bd10815259e58binary/#Write

示例:

package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

func main() {
	buf := new(bytes.Buffer)
	var pi int64 = 255

	err := binary.Write(buf, binary.LittleEndian, pi)
	if err != nil {
		fmt.Println("binary.Write failed:", err)
	}
	fmt.Println( buf.Bytes())
}
//输出:
[255 0 0 0 0 0 0 0]

这里需要注意:如果序列化的类型是 int 类型的话,将会报错:

binary.Write failed: binary.Write: invalid type int

而且,序列化的值是空的。

这是由于,他在前面已经解释清楚了,只能序列化固定大小的类型(bool,int8,uint8,int16,float32,complex64…),或者是结构体和固定大小的数组。

其他序列化方法

当然,go语言还有其他的序列化方法,如 protobuf 协议,参考:https://geektutu.com/post/quick-go-protobuf.html

【相关推荐:Go视频教程编程教学

以上是golang序列化方法有哪些的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
GO的選擇語句:多路復用並發操作GO的選擇語句:多路復用並發操作Apr 24, 2025 pm 05:21 PM

go'SselectStatementTreamLinesConcurrentProgrambyMultiplexingOperations.1)itallowSwaitingOnMultipleChannEloperations,執行thefirstreadyone.2)theDefirstreadyone.2)thedefefcasepreventlocksbysbysbysbysbysbythoplocktrograpraproxrograpraprocrecrecectefnoopeready.3)

GO中的高級並發技術:上下文和候補組GO中的高級並發技術:上下文和候補組Apr 24, 2025 pm 05:09 PM

contextancandwaitgroupsarecrucialingoformanaginggoroutineseflect.1)context contextsallowsAllowsAllowsAllowsAllowsAllingCancellationAndDeadLinesAcrossapibiboundaries,確保GoroutinesCanbestoppedGrace.2)WaitGroupsSynChronizeGoroutines,確保Allimizegoroutines,確保AllizeNizeGoROutines,確保AllimizeGoroutines

使用微服務體系結構的好處使用微服務體系結構的好處Apr 24, 2025 pm 04:29 PM

goisbeneformervicesduetoitssimplicity,效率,androbustConcurrencySupport.1)go'sdesignemphasemphasizessimplicity and效率,Idealformicroservices.2))其ConcconcurnCurnInesSandChannelsOdinesSallessallessallessAlloSalosalOsalOsalOsalOndlingConconcConccompi.3)

Golang vs. Python:利弊Golang vs. Python:利弊Apr 21, 2025 am 12:17 AM

Golangisidealforbuildingscalablesystemsduetoitsefficiencyandconcurrency,whilePythonexcelsinquickscriptinganddataanalysisduetoitssimplicityandvastecosystem.Golang'sdesignencouragesclean,readablecodeanditsgoroutinesenableefficientconcurrentoperations,t

Golang和C:並發與原始速度Golang和C:並發與原始速度Apr 21, 2025 am 12:16 AM

Golang在並發性上優於C ,而C 在原始速度上優於Golang。 1)Golang通過goroutine和channel實現高效並發,適合處理大量並發任務。 2)C 通過編譯器優化和標準庫,提供接近硬件的高性能,適合需要極致優化的應用。

為什麼要使用Golang?解釋的好處和優勢為什麼要使用Golang?解釋的好處和優勢Apr 21, 2025 am 12:15 AM

選擇Golang的原因包括:1)高並發性能,2)靜態類型系統,3)垃圾回收機制,4)豐富的標準庫和生態系統,這些特性使其成為開發高效、可靠軟件的理想選擇。

Golang vs.C:性能和速度比較Golang vs.C:性能和速度比較Apr 21, 2025 am 12:13 AM

Golang適合快速開發和並發場景,C 適用於需要極致性能和低級控制的場景。 1)Golang通過垃圾回收和並發機制提升性能,適合高並發Web服務開發。 2)C 通過手動內存管理和編譯器優化達到極致性能,適用於嵌入式系統開發。

golang比C快嗎?探索極限golang比C快嗎?探索極限Apr 20, 2025 am 12:19 AM

Golang在編譯時間和並發處理上表現更好,而C 在運行速度和內存管理上更具優勢。 1.Golang編譯速度快,適合快速開發。 2.C 運行速度快,適合性能關鍵應用。 3.Golang並發處理簡單高效,適用於並發編程。 4.C 手動內存管理提供更高性能,但增加開發複雜度。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)