Go (Golang) 中的对象序列化:从 JSON 到 Protobuf
序列化是将数据结构(对象、切片、映射)转换为字节序列的过程,以便保存到文件、通过网络传输或缓存。逆过程是反序列化。在 Go (Golang) 中,此任务由内置包和第三方库解决。工具的选择取决于对速度、数据大小、可读性以及与其他语言兼容性的要求。
1. 内置包 encoding/json
Go 中最流行的序列化方式。JSON 是一种人类可读、跨平台的格式。encoding/json 包提供了 Marshal 和 Unmarshal 函数。
package main
import ( "encoding/json" "fmt" "log")
type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email,omitempty"`}
func main() { user := User{ID: 1, Name: "Alice", Email: "alice@example.com"}
// 序列化 jsonData, err := json.Marshal(user) if err != nil { log.Fatal(err) } fmt.Println(string(jsonData)) // {"id":1,"name":"Alice","email":"alice@example.com"}
// 反序列化 var decoded User err = json.Unmarshal(jsonData, &decoded) if err != nil { log.Fatal(err) } fmt.Printf("%+v", decoded)}特点:
- 支持结构体标签以自定义字段名称。
- 适用于切片、映射、嵌套结构体。
- 比二进制格式慢,但便于调试。
- 不支持循环引用。
2. encoding/xml — XML 序列化
XML 用于 SOAP、RSS、配置文件。encoding/xml 包的工作方式与 JSON 类似,但使用 xml 标签。
type Book struct { Title string `xml:"title"` Author string `xml:"author"` Pages int `xml:"pages,attr"`}
func main() { book := Book{Title: "Go in Action", Author: "William Kennedy", Pages: 500} xmlData, _ := xml.MarshalIndent(book, "", " ") fmt.Println(string(xmlData)) // <Book pages="500"> // <title>Go in Action</title> // <author>William Kennedy</author> // </Book>}何时使用:
- 与遗留系统集成。
- 严格的模式 (XSD)。
- 面向文档的数据。
3. encoding/gob — Go 原生二进制格式
encoding/gob 包专为 Go 设计。它能高效地将数据编码为二进制格式,支持复杂类型(接口、通道、函数——有限制)。
import "encoding/gob"
type Task struct { ID int Status string}
func main() { var network bytes.Buffer enc := gob.NewEncoder(&network) dec := gob.NewDecoder(&network)
task := Task{ID: 42, Status: "done"} err := enc.Encode(task) if err != nil { log.Fatal(err) }
var restored Task err = dec.Decode(&restored) fmt.Println(restored) // {42 done}}优点:
- 高速且紧凑。
- 自动类型注册。
- 支持循环结构。
缺点: 与其他语言不兼容。
4. Protocol Buffers (protobuf) — 快速二进制序列化
由 Google 开发。需要在 .proto 文件中定义模式,并通过 protoc 生成代码。google.golang.org/protobuf 库是现代标准。
// user.proto// syntax = "proto3";// message User {// int32 id = 1;// string name =