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.
| Nom | XML | YAML | JSON | Protocol Buffers |
|---|---|---|---|---|
| Structure de données | Complexe | Relativement simple | Simple | Relativement complexe |
| Mode de stockage | Texte | Texte | Texte | Binaire |
| Taille de stockage | Grande | Moyenne | Moyenne | Petite |
| Efficacité d'analyse | Lente | Moyenne | Moyenne | Rapide |
| Support linguistique | Très nombreux | Nombreux | Très nombreux | Relativement nombreux |
| Difficulté de développement | Fastidieuse | Relativement simple | Simple | Simple |
| Coût d'apprentissage | Faible | Faible | Faible | Faible |
| Domaine d'application | Échange de données | Fichier 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
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) //sérialisation xml
func MarshalIndent(v any, prefix, indent string) ([]byte, error) //formatage
func Unmarshal(data []byte, v any) error //désérialisationSérialisation
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
<Person>
<id>120</id>
<name>jack</name>
<age>18</age>
<address>usa</address>
</Person>Désérialisation
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
{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.
go get github.com/go-yaml/yamlMéthodes principales
func Marshal(in interface{}) (out []byte, err error) //sérialisation
func Unmarshal(in []byte, out interface{}) (err error) //désérialisationD'abord, préparons une structure
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
database: mysql
url: 127.0.0.1
port: 3306
username: root
password: 123456Sérialisation
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
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
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.
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 GoD'abord, définissons une structure
type Person struct {
UserId string
Username string
Age int
Address string
}Sérialisation
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
{ "UserId": "120", "Username": "jack", "Age": 18, "Address": "usa" }Renommage de champs
Nous pouvons utiliser les tags de structure pour obtenir un effet de renommage.
type Person struct {
UserId string `json:"id"`
Username string `json:"name"`
Age int `json:"age"`
Address string `json:"address"`
}Sortie à ce moment
{ "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.
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))
}Sortie
{
"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é.
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
{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/protoFichier person.proto
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
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_MAILCependant, 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.
