Maison >développement back-end >Golang >golang : Désorganisation des commentaires YAML dynamiques

golang : Désorganisation des commentaires YAML dynamiques

WBOY
WBOYavant
2024-02-09 11:00:14800parcourir

golang:解组动态 YAML 注释

l'éditeur php Baicao vous propose un article sur Golang, intitulé "Unmarshalling Dynamic YAML Comments". Cet article présentera en détail comment analyser les fichiers YAML contenant des commentaires dans Golang et associer les informations de commentaire aux données correspondantes. Grâce à cet article, vous apprendrez à utiliser le package yaml.v3 du langage Go pour implémenter cette fonction et pourrez l'appliquer de manière flexible dans vos propres projets. Que vous soyez débutant ou développeur expérimenté, cet article vous apportera de précieuses connaissances et conseils. Commençons!

Contenu de la question

Je souhaite changer dynamiquement struct 的注释并使用 yaml.unmarshal comme suit :

package main

import (
    "fmt"
    "reflect"

    "gopkg.in/yaml.v3"
)

type User struct {
    Name string `yaml:"dummy"`
}

func (u *User) UnmarshalYAML(node *yaml.Node) error {
    value := reflect.ValueOf(*u)
    t := value.Type()
    fields := make([]reflect.StructField, 0)

    for i := 0; i < t.NumField(); i++ {
        fields = append(fields, t.Field(i))

        if t.Field(i).Name == "Name" {
            fields[i].Tag = `yaml:"name"` // Dynamic annotation
        }
    }

    newType := reflect.StructOf(fields)
    newValue := value.Convert(newType)

    err := node.Decode(newValue.Interface()) // Cause error because it's not pointer
    return err
}

var dat string = `name: abc`

func main() {
    out := User{}
    yaml.Unmarshal([]byte(dat), &out)
    fmt.Printf("%+v\n", out)
}

Cela empêche des éléments comme panic:reflect:reflect.value.set using unaddressable value [recovered] 这样的错误,我认为这是因为 node.decode d'être utilisés avec des pointeurs. Alors, comment créer un nouveau type de pointeur ?

Solution de contournement

Voici une démo mise à jour et fonctionnelle :

package main

import (
    "fmt"
    "reflect"
    "unsafe"

    "gopkg.in/yaml.v3"
)

type User struct {
    Name string `yaml:"dummy"`
}

func (u *User) UnmarshalYAML(node *yaml.Node) error {
    t := reflect.TypeOf(*u)
    fields := make([]reflect.StructField, 0)

    for i := 0; i < t.NumField(); i++ {
        fields = append(fields, t.Field(i))

        if t.Field(i).Name == "Name" {
            fields[i].Tag = `yaml:"name"` // Dynamic annotation
        }
    }

    newType := reflect.StructOf(fields)
    newValue := reflect.NewAt(newType, unsafe.Pointer(u)).Elem()

    err := node.Decode(newValue.Addr().Interface())
    return err
}

var dat string = `name: abc`

func main() {
    out := User{}
    yaml.Unmarshal([]byte(dat), &out)
    fmt.Printf("%+v\n", out)
}

Deux changements clés :

  1. volonté newvalue.interface() 替换为 newvalue.addr().interface(). (Voir cet exemple : https://www.php.cn/link/e96c7de8f6390b1e6c71556e4e0a4959 a>)

  2. volonté newvalue := value.convert(newtype) 替换为 newvalue := reflect.newat(newtype, unsafe.pointer(u)).elem().

    Nous faisons cela parce que value :=reflect.valueof(*u) 中的 value 是不可寻址的(您可以使用 fmt.printf("%v", value.addr()) 进行验证。它会出现错误并显示消息 panic : 不可寻址值的reflect.value.addr().

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer
Article précédent:Formatage de chaîne GolangArticle suivant:Formatage de chaîne Golang