Maison  >  Article  >  développement back-end  >  Comment puis-je réutiliser une structure d'un package tiers tout en modifiant le comportement de marshalling des champs individuels ?

Comment puis-je réutiliser une structure d'un package tiers tout en modifiant le comportement de marshalling des champs individuels ?

PHPz
PHPzavant
2024-02-10 08:18:08973parcourir

Comment puis-je réutiliser une structure dun package tiers tout en modifiant le comportement de marshalling des champs individuels ?

L'éditeur PHP Zimo est là pour partager une astuce sur la façon de réutiliser les structures dans des packages tiers et de modifier le comportement de marshalling d'un seul champ. Lorsque nous utilisons un package tiers, nous devons parfois y personnaliser un champ. Cet article présentera une méthode simple permettant d'atteindre cet objectif grâce à l'héritage et à l'écrasement, qui peut non seulement réutiliser la structure originale mais également répondre à des besoins personnalisés. Examinons ensuite la méthode de mise en œuvre spécifique !

Contenu de la question

Supposons que je veuille rassembler une structure en YAML et que la structure ait déjà toutes ses balises YAML définies, à l'exception d'une que je souhaite modifier. Comment puis-je modifier le comportement de ce champ unique sans modifier la structure elle-même ? Supposons que la structure provienne d’un package tiers.

Voici un exemple à démontrer, et ma meilleure tentative. Supposons que les User 结构(及其关联的 Secret structures) proviennent de packages tiers, nous ne pouvons donc pas les modifier.

package main

import (
    "fmt"

    "gopkg.in/yaml.v2"
)

type User struct {
    Email    string  `yaml:"email"`
    Password *Secret `yaml:"password"`
}

type Secret struct {
    s string
}

// MarshalYAML implements the yaml.Marshaler interface for Secret.
func (sec *Secret) MarshalYAML() (interface{}, error) {
    if sec != nil {
        // Replace `"<secret>"` with `sec.s`, and it gets the desired
        // behavior. But I can't change the Secret struct:
        return "<secret>", nil
    }
    return nil, nil
}

func (sec *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error {
    var st string
    if err := unmarshal(&st); err != nil {
        return err
    }
    sec.s = st
    return nil
}

// My best attempt at the solution:
type SolutionAttempt struct {
    User
}

func (sol *SolutionAttempt) MarshalYAML() (interface{}, error) {
    res, err := yaml.Marshal(
        struct {
            // I don't like having to repeat all these fields from User:
            Email    string `yaml:"email"`
            Password string `yaml:"password"`
        }{
            Email:    sol.User.Email,
            Password: sol.User.Password.s,
        },
    )
    if err != nil {
        return nil, err
    }
    return string(res), nil
}

func main() {
    user := &User{}
    var data = `
  email: [email&#160;protected]
  password: asdf
`
    err := yaml.Unmarshal([]byte(data), user)
    if err != nil {
        fmt.Printf("errors! %s", err)
        return
    }

    buf, err := yaml.Marshal(user)
    if err != nil {
        fmt.Printf("errors! %s", err)
        return
    }

    // Without touching User or Secret, how can I unmarshall an
    // instance of User that renders the secret?
    fmt.Printf("marshalled output:\n%s\n", buf)

    ///////////////////////////////////////////////////////
    // attempted solution:
    ///////////////////////////////////////////////////////
    sol := &SolutionAttempt{}
    var data2 = `
user:
    email: [email&#160;protected]
    password: asdf
`
    err = yaml.Unmarshal([]byte(data2), sol)
    if err != nil {
        fmt.Printf("errors! %s", err)
        return
    }

    buf, err = yaml.Marshal(sol)
    if err != nil {
        fmt.Printf("errors! %s", err)
        return
    }
    fmt.Printf("attempted solution marshalled output:\n%s\n", buf)
}

Voici le lien Go Playground pour le code ci-dessus : https://go.dev/play/p/ojiPv4ylCEq

Solution de contournement

Ceci n'est tout simplement pas possible.

Votre « meilleur essai » est le bon chemin.

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