Skip to content

Go Sprache encode Kodierung und Dekodierung

Im heutigen Internetzeitalter sind die am häufigsten verwendeten sprachunabhängigen Datenformate xml, Yaml, json, protobuf. Go unterstützt ebenfalls die Operationen mit diesen Datenformaten. Die folgende Tabelle zeigt einen Vergleich.

NameXMLYAMLJSONProtocol Buffers
DatenstrukturKomplexEinfacherEinfachKomplexer
SpeicherformatTextTextTextBinär
SpeichergrößeGroßMittelMittelKlein
Parsing-EffizienzLangsamMittelMittelSchnell
SprachunterstützungSehr vieleVieleVieleZiemlich viele
EntwicklungsschwierigkeitUmständlichEinfacherEinfachEinfach
LernkurveNiedrigNiedrigNiedrigNiedrig
AnwendungsbereichDatenaustauschKonfigurationsdateiDatenaustauschDatenaustausch

TIP

In Go müssen Felder öffentlich zugänglich sein (d.h. mit großem Anfangsbuchstaben), wenn man Strukturen serialisieren und deserialisieren möchte.

Darüber hinaus wird TOML immer beliebter. Die Syntax ähnelt einer Verbesserung von .ini. Interessierte können unter TOML: Toms offensichtliche, minimale Konfigurationssprache mehr erfahren.

XML

xml, auch bekannt als eXtensible Markup Language, ist ein Format zum Speichern von Daten. Es entstand in den 1960er Jahren und ist das älteste der oben genannten Datenformate. Es wird vielseitig eingesetzt: für Netzwerkübertragung, Datenaustausch, Konfigurationsdateien, Datenspeicherung und mehr. Mit der Zeit wird es jedoch zunehmend durch neuere Auszeichnungssprachen ersetzt.

Zuerst definieren wir eine Struktur:

go
type Person struct {
   UserId   string `xml:"id"`
   Username string `xml:"name"`
   Age      int    `xml:"age"`
   Address  string `xml:"address"`
}
go
func Marshal(v any) ([]byte, error) //XML-Serialisierung

func MarshalIndent(v any, prefix, indent string) ([]byte, error) //Formatierung

func Unmarshal(data []byte, v any) error //Deserialisierung

Serialisierung

go
func main() {
   person := Person{
      UserId:   "120",
      Username: "jack",
      Age:      18,
      Address:  "usa",
   }

   bytes, err := xml.MarshalIndent(person, "", "\t")
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(string(bytes))
}

Ausgabe

xml
<Person>
        <id>120</id>
        <name>jack</name>
        <age>18</age>
        <address>usa</address>
</Person>

Deserialisierung

go
func main() {
   var person = Person{
      UserId:   "",
      Username: "",
      Age:      0,
      Address:  "",
   }

   xmlStr := "<Person>                      \n        <id>120</id>          \n        <name>jack</name>     \n        <age>18</age>         \n        <address>usa</address>\n</Person>  "

   err := xml.Unmarshal([]byte(xmlStr), &person)
   if err != nil {
      fmt.Println(err)
      return
   }
}

Ausgabe

go
{UserId:120 Username:jack Age:18 Address:usa}

Die traditionelle XML-Analyse erfordert jedoch oft das Erstellen neuer Strukturen, was sehr umständlich sein kann. Aktuell werden meist einfache XML-Strukturen analysiert. Bei komplexen Strukturen kann dies sehr mühsam werden. Deshalb verwenden die meisten eine Open-Source-Bibliothek eines Drittanbieters wie etree für die XML-Analyse. Interessierte können sich hier informieren: Go nützliches Plugin etree zum Analysieren von XML-Dateien -掘金 (juejin.cn).

YML

Die Syntax von YAML ähnelt anderen höheren Programmiersprachen und kann einfach Listen, Hash-Tabellen, Skalare und andere Datenformen ausdrücken. Es verwendet Leerzeichen für Einrückungen und ist stark vom Erscheinungsbild abhängig. Es eignet sich besonders gut zum Ausdrücken oder Bearbeiten von Datenstrukturen und verschiedenen Konfigurationsdateien. YML existiert in vielen Projekten als Konfigurationsdatei, mit einer klareren und übersichtlicheren Inhaltsstruktur. Die offizielle Go-Unterstützung bietet keine YML-Unterstützung, daher müssen wir ein Paket eines Drittanbieters verwenden.

powershell
go get github.com/go-yaml/yaml

Hauptmethoden

go
func Marshal(in interface{}) (out []byte, err error) //Serialisierung

func Unmarshal(in []byte, out interface{}) (err error) //Deserialisierung

Zuerst bereiten wir eine Struktur vor

go
type Config struct {
   Database string `yaml:"database"`
   Url      string `yaml:"url"`
   Port     int    `yaml:"port"`
   Username string `yaml:"username"`
   Password string `yaml:"password"`
}

Konfigurationsdatei

yaml
database: mysql
url: 127.0.0.1
port: 3306
username: root
password: 123456

Serialisierung

go
func main() {
   config := Config{
      Database: "oracle",
      Url:      "localhost",
      Port:     3326,
      Username: "root",
      Password: "123456",
   }

   out, err := yaml.Marshal(config)
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(string(out))
}

Ausgabe

yaml
database: oracle
url: localhost
port: 3326
username: root
password: "123456"

Da yml jedoch eine strikte Einrückungssyntax hat, gibt es keine Probleme mit der Serialisierungsformatierung.

Deserialisierung

go
func main() {
   bytes, err := os.ReadFile("./src/config.yml")
   if err != nil {
      fmt.Println(err)
      return
   }
   var config Config
   err = yaml.Unmarshal(bytes, &config)
   if err != nil {
      fmt.Println(err)
      return
   }

   fmt.Println(config)
}

Ausgabe

{mysql 127.0.0.1 3306 root 123456}

JSON

json wird häufig in der Restful-Schnittstellenkommunikation verwendet. Im Vergleich zu xml ist es leichter und hat eine niedrige Lernkurve, was es im Web-Bereich zum dominierenden Datenaustauschformat gemacht hat.

In Go stellt das Paket encoding/json entsprechende Funktionen für die JSON-Serialisierung und -Deserialisierung bereit. Die wichtigsten Funktionen sind:

go
func Marshal(v any) ([]byte, error) //Serialisiert ein Go-Objekt in einen JSON-String

func Unmarshal(data []byte, v any) error //Deserialisiert einen JSON-String in ein Go-Objekt

Zuerst definieren wir eine Struktur

go
type Person struct {
   UserId   string
   Username string
   Age      int
   Address  string
}

Serialisierung

go
func main() {
  person := Person{
    UserId:   "120",
    Username: "jack",
    Age:      18,
    Address:  "usa",
  }

  bytes, err := json.Marshal(person)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(bytes))
}

Ergebnis

json
{ "UserId": "120", "Username": "jack", "Age": 18, "Address": "usa" }

Feld umbenennen

Wir können durch Struktur-Tags eine Umbenennung erreichen.

go
type Person struct {
   UserId   string `json:"id"`
   Username string `json:"name"`
   Age      int    `json:"age"`
   Address  string `json:"address"`
}

Ausgabe

json
{ "id": "1202", "name": "jack", "age": 19, "address": "USA" }

Einrückung

Bei der Serialisierung gibt es standardmäßig keine Einrückung, um den Platzbedarf während der Übertragung zu reduzieren. Dies ist jedoch nicht für die menschliche Betrachtung geeignet. In einigen Fällen müssen wir sie in eine für Menschen lesbare Form serialisieren. Dazu genügt ein Funktionswechsel.

go
func MarshalIndent(v any, prefix, indent string) ([]byte, error)
go
func main() {
   person := Person{
      UserId:   "1202",
      Username: "jack",
      Age:      19,
      Address:  "USA",
   }
   bytes, err := json.MarshalIndent(person, "", "\t")
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(string(bytes))
}

Ausgabe

json
{
  "id": "1202",
  "name": "jack",
  "age": 19,
  "address": "USA"
}

Deserialisierung

Bei der Deserialisierung ist zu beachten: Wenn die Struktur ein JSON-Tag hat, hat der JSON-Tag Vorrang vor dem Feldnamen. Andernfalls gilt der Struktur-Attributname.

go
func main() {
  person := Person{}

  jsonStr := "{\"id\":\"120\",\"name\":\"jack\",\"age\":18,\"address\":\"usa\"}\n"

  err := json.Unmarshal([]byte(jsonStr), &person)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Printf("%+v", person)
}

Ausgabe

go
{UserId:120 Username:jack Age:18 Address:usa}

Protocol Buffers

Protocol Buffers ist ein 2008 von Google open-source veröffentlichter, sprachneutraler, protokollneutraler, erweiterbarer Mechanismus für die Serialisierung strukturierter Daten. Im Vergleich zu den oben genannten drei Formaten ist es leichter und schneller beim Packen und Entpacken. Es wird häufig im RPC-Bereich für die Kommunikation verwendet. Weitere Informationen zu Protobuf finden Sie unter Protobuf.

Abhängigkeit installieren

go get github.com/golang/protobuf/proto

person.proto Datei

protobuf
syntax = "proto3";

option go_package = "./;person";

package proto;

enum Gender{
  MAIL = 0;
  FE_MAIL = 1;
}

message person {
  string name = 1;
  int32 age = 2;
  Gender gender = 3;
}

Nach dem Generieren der Datei

go
package main

import (
   p "GoProject/src/proto"
   "fmt"
   "github.com/golang/protobuf/proto"
)

func main() {
  person := p.Person{
    Name:   "wyh",
    Age:    12,
    Gender: p.Gender_FE_MAIL,
  }

  data, err := proto.Marshal(&person)//Serialisierung
  if err != nil {
    fmt.Println(err)
    return
  }
  temp := &p.Person{}
  fmt.Println("proto buffer len: ", len(data), "bytes:", data)
  err = proto.Unmarshal(data, temp)//Deserialisierung
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(temp)
}

Ausgabe

proto buffer len:  9 bytes: [10 3 119 121 104 16 12 24 1]
name:"wyh"  age:12  gender:FE_MAIL

Normalerweise serialisieren wir jedoch nicht manuell. Der protoc-Compiler kann aus der definierten proto-Datei den Quellcode der entsprechenden Sprache generieren.

Golang by www.golangdev.cn edit