Skip to content

Go encode encodage décodage

À l'ère actuelle d'Internet, les formats de données indépendants du langage les plus couramment utilisés sont xml, Yaml, json, protobuf. Go prend également en charge les opérations liées à ces formats de données, comme indiqué dans le tableau comparatif ci-dessous.

NomXMLYAMLJSONProtocol Buffers
Structure de donnéesComplexeRelativement simpleSimpleRelativement complexe
Mode de stockageTexteTexteTexteBinaire
Taille de stockageGrandeMoyenneMoyennePetite
Efficacité d'analyseLenteMoyenneMoyenneRapide
Support linguistiqueTrès nombreuxNombreuxTrès nombreuxRelativement nombreux
Difficulté de développementFastidieuseRelativement simpleSimpleSimple
Coût d'apprentissageFaibleFaibleFaibleFaible
Domaine d'applicationÉchange de donnéesFichier de configurationÉchange de donnéesÉchange de données

TIP

En Go, si vous souhaitez sérialiser et désérialiser des structures, les champs doivent être exportés, c'est-à-dire que leur première lettre doit être en majuscule.

De plus, TOML devient également progressivement populaire. Sa syntaxe ressemble à une amélioration de .ini. Si vous êtes intéressé, vous pouvez consulter TOML : Langage minimaliste (sémantiquement) évident de Tom pour les fichiers de configuration pour en savoir plus.

XML

xml, également connu sous le nom de eXtensible Markup Language, est un format utilisé pour stocker des données. Il trouve son origine dans les années 1960 et est le plus ancien des formats de données mentionnés ci-dessus. Son utilisation est très répandue, notamment pour la transmission réseau, l'échange de données, les fichiers de configuration, le stockage de données, etc. Cependant, avec l'évolution technologique, il est progressivement remplacé par de nouveaux langages de balisage.

D'abord, définissons une structure

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) //sérialisation xml

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

func Unmarshal(data []byte, v any) error //désérialisation

Sérialisation

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))
}

Sortie

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

Désérialisation

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
   }
}

Sortie

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

Cependant, l'analyse XML traditionnelle nécessite souvent de créer de nouvelles structures, ce qui peut être fastidieux. Les exemples ci-dessus montrent des structures XML simples. Si vous utilisez des structures complexes, cela peut devenir très difficile. C'est pourquoi nous utilisons généralement une bibliothèque open source tierce etree pour analyser XML. Si vous êtes intéressé, vous pouvez en savoir plus : Plugin Go etree pour l'analyse de fichiers XML - Juejin (juejin.cn).

YML

La syntaxe YAML est similaire à celle d'autres langages de haut niveau et peut exprimer simplement des listes, des tables de hachage, des scalaires et d'autres formes de données. Elle utilise des symboles d'espacement pour l'indentation et dépend largement de l'apparence, ce qui la rend particulièrement adaptée pour exprimer ou éditer des structures de données, divers fichiers de configuration. YML existe également sous forme de fichiers de configuration dans de nombreux projets. Sa structure de contenu est plus concise et claire d'un coup d'œil. Go ne fournit pas officiellement de support pour YML, nous devons donc utiliser un package tiers.

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

Méthodes principales

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

func Unmarshal(in []byte, out interface{}) (err error) //désérialisation

D'abord, préparons une structure

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

Fichier de configuration

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

Sérialisation

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))
}

Sortie

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

Cependant, comme yml a une syntaxe d'indentation stricte, il n'y a pas de problème de formatage de sérialisation.

Désérialisation

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)
}

Sortie

{mysql 127.0.0.1 3306 root 123456}

JSON

json est fréquemment utilisé dans la communication d'interfaces de style Restful. Sa taille plus légère par rapport à xml et son faible coût d'apprentissage en ont fait le format d'échange de données principal dans le domaine web.

En Go, le package encoding/json fournit des fonctions correspondantes pour la sérialisation et la désérialisation JSON. Les fonctions principales sont les suivantes.

go
func Marshal(v any) ([]byte, error) //sérialise un objet Go en chaîne JSON

func Unmarshal(data []byte, v any) error //désérialise une chaîne JSON en objet Go

D'abord, définissons une structure

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

Sérialisation

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))
}

Résultat

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

Renommage de champs

Nous pouvons utiliser les tags de structure pour obtenir un effet de renommage.

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

Sortie à ce moment

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

Indentation

Par défaut, la sérialisation n'a aucune indentation, afin de réduire la consommation d'espace lors de la transmission. Cependant, cela n'est pas propice à l'observation humaine. Dans certains cas, nous devons la sérialiser sous une forme observable par l'homme. Pour cela, il suffit d'utiliser une autre fonction.

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))
}

Sortie

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

Désérialisation

Lors de la désérialisation, il faut noter que si la structure a un tag JSON, le nom du champ est déterminé en priorité par le tag JSON, sinon le nom de l'attribut de la structure est utilisé.

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)
}

Sortie

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

Protocol Buffers

Protocol est un mécanisme de sérialisation de données structurées, neutre en termes de langage et de protocole, open source par Google en 2008. Comparé aux trois précédents, il est plus léger et plus rapide lors des opérations d'empaquetage et de dépaquetage. Il est principalement utilisé dans le domaine de la communication RPC. Pour plus d'informations sur Protobuf, vous pouvez consulter Protobuf.

Installation des dépendances

go get github.com/golang/protobuf/proto

Fichier person.proto

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;
}

Après avoir généré le fichier

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)//sérialisation
  if err != nil {
    fmt.Println(err)
    return
  }
  temp := &p.Person{}
  fmt.Println("proto buffer len: ", len(data), "bytes:", data)
  err = proto.Unmarshal(data, temp)//désérialisation
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(temp)
}

Sortie

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

Cependant, nous ne sérialisons généralement pas manuellement. Le compilateur protoc peut générer le code source dans le langage correspondant à partir des fichiers proto que nous avons définis.

Golang by www.golangdev.cn edit