Go (Golang) 中的对象序列化:从 JSON 到 Protobuf
序列化(编组)是将数据结构(对象)转换为字节序列以便通过网络传输或保存到磁盘的过程。反向过程是反序列化(解组)。在 Go 中,此问题通过标准库和第三方包解决。让我们看看主要方法。
1. 标准库:encoding/json
最流行的方法。使用 encoding/json 包进行序列化。
基本示例
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"}
// 序列化 (Marshal) jsonData, err := json.Marshal(user) if err != nil { log.Fatal(err) } fmt.Println(string(jsonData)) // {"id":1,"name":"Alice","email":"alice@example.com"}
// 反序列化 (Unmarshal) var decoded User err = json.Unmarshal(jsonData, &decoded) if err != nil { log.Fatal(err) } fmt.Printf("%+v", decoded) // {ID:1 Name:Alice Email:alice@example.com}}重要的结构体标签
json:"field_name"— 设置 JSON 中的字段名称,omitempty— 如果字段为空(例如空字符串、0、nil),则跳过该字段,string— 强制数字字段的字符串表示形式-— 在序列化时忽略该字段
2. XML 序列化:encoding/xml
encoding/xml 包的工作原理类似,但使用 XML 标签。
package main
import ( "encoding/xml" "fmt")
type Person struct { XMLName xml.Name `xml:"person"` Name string `xml:"name"` Age int `xml:"age,attr"`}
func main() { p := Person{Name: "Bob", Age: 30} xmlData, _ := xml.MarshalIndent(p, "", " ") fmt.Println(string(xmlData)) // 输出: // <person age="30"> // <name>Bob</name> // </person>}支持属性 (,attr)、嵌套元素、CDATA 和命名空间。
3. 二进制序列化:encoding/gob
gob 包是 Go 用于二进制序列化的自有格式。非常适合 Go 应用程序之间的数据交换。
package main
import ( "bytes" "encoding/gob" "fmt" "log")
type Data struct { X, Y int Label string}
func main() { var buf bytes.Buffer enc := gob.NewEncoder(&buf) data := Data{X: 10, Y: 20, Label: "test"}
// 编码 if err := enc.Encode(data); err != nil { log.Fatal(err) }
// 解码 var decoded Data dec := gob.NewDecoder(&buf) if err := dec.Decode(&decoded); err != nil { log.Fatal(err) } fmt.Printf("%+v", decoded) // {X:10 Y:20 Label:test}}gob 的特点:
- 需要预先注册类型(如果使用接口)
- 对于二进制数据比 JSON 更紧凑
- 不被其他语言支持(仅限 Go)
4. Protocol Buffers (protobuf)
Google 用于高效二进制序列化的协议。需要安装 protoc 和 protoc-gen-go 插件。
步骤 1:定义模式 (user.proto)
syntax = "proto3";package main;
message User { int32 id = 1; string name = 2; string email = 3;}步骤 2:生成代码
protoc --go_out=. user.proto
图书馆中也有
推荐