Maison > développement back-end > Golang > le corps du texte

golang : Désorganisation des commentaires YAML dynamiques

WBOY
Libérer: 2024-02-09 11:00:14
avant
795 Les gens l'ont consulté

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)
}
Copier après la connexion

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)
}
Copier après la connexion

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!

Étiquettes associées:
source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal