Сериализация объектов в 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\n", 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\n", 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
Шаг 3: Использование в Go
package main
import (
"fmt"
"log"
"google.golang.org/protobuf/proto"
)
func main() {
user := &User{
Id: 1,
Name: "Charlie