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.
| Name | XML | YAML | JSON | Protocol Buffers |
|---|---|---|---|---|
| Datenstruktur | Komplex | Einfacher | Einfach | Komplexer |
| Speicherformat | Text | Text | Text | Binär |
| Speichergröße | Groß | Mittel | Mittel | Klein |
| Parsing-Effizienz | Langsam | Mittel | Mittel | Schnell |
| Sprachunterstützung | Sehr viele | Viele | Viele | Ziemlich viele |
| Entwicklungsschwierigkeit | Umständlich | Einfacher | Einfach | Einfach |
| Lernkurve | Niedrig | Niedrig | Niedrig | Niedrig |
| Anwendungsbereich | Datenaustausch | Konfigurationsdatei | Datenaustausch | Datenaustausch |
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:
type Person struct {
UserId string `xml:"id"`
Username string `xml:"name"`
Age int `xml:"age"`
Address string `xml:"address"`
}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 //DeserialisierungSerialisierung
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
<Person>
<id>120</id>
<name>jack</name>
<age>18</age>
<address>usa</address>
</Person>Deserialisierung
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
{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.
go get github.com/go-yaml/yamlHauptmethoden
func Marshal(in interface{}) (out []byte, err error) //Serialisierung
func Unmarshal(in []byte, out interface{}) (err error) //DeserialisierungZuerst bereiten wir eine Struktur vor
type Config struct {
Database string `yaml:"database"`
Url string `yaml:"url"`
Port int `yaml:"port"`
Username string `yaml:"username"`
Password string `yaml:"password"`
}Konfigurationsdatei
database: mysql
url: 127.0.0.1
port: 3306
username: root
password: 123456Serialisierung
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
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
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:
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-ObjektZuerst definieren wir eine Struktur
type Person struct {
UserId string
Username string
Age int
Address string
}Serialisierung
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
{ "UserId": "120", "Username": "jack", "Age": 18, "Address": "usa" }Feld umbenennen
Wir können durch Struktur-Tags eine Umbenennung erreichen.
type Person struct {
UserId string `json:"id"`
Username string `json:"name"`
Age int `json:"age"`
Address string `json:"address"`
}Ausgabe
{ "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.
func MarshalIndent(v any, prefix, indent string) ([]byte, error)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
{
"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.
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
{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/protoperson.proto Datei
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
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_MAILNormalerweise serialisieren wir jedoch nicht manuell. Der protoc-Compiler kann aus der definierten proto-Datei den Quellcode der entsprechenden Sprache generieren.
