首頁  >  文章  >  後端開發  >  如何重複使用第三方套件中的結構,同時變更單一欄位的編組行為?

如何重複使用第三方套件中的結構,同時變更單一欄位的編組行為?

PHPz
PHPz轉載
2024-02-10 08:18:08975瀏覽

如何重複使用第三方套件中的結構,同時變更單一欄位的編組行為?

php小編子墨在這裡分享一個關於如何重複使用第三方包中的結構並更改單一欄位編組行為的技巧。當我們使用第三方套件時,有時我們需要對其中的某個欄位進行自訂編組。本文將介紹一個簡單的方法,可以透過繼承和重寫的方式來實現這一目標,既能重複使用原有的結構,又能滿足個人化需求。接下來讓我們一起來看看具體的實作方法吧!

問題內容

假設我想將一個結構編組到 YAML 中,並且該結構已經定義了其所有 YAML 標記,但有一個我想要更改的標記除外。如何在不更改結構本身的情況下更改此單一欄位的行為?假設該結構來自第三方套件。

這是一個要示範的範例,以及我的最佳嘗試。假設 User 結構(及其關聯的 Secret 結構)來自第三方包,因此我們無法修改它們。

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

這是上述程式碼的 Go Playground 連結:https://go.dev/play/p/ojiPv4ylCEq

解決方法

這根本不可能。

你的「最佳嘗試」就是正確的道路。

以上是如何重複使用第三方套件中的結構,同時變更單一欄位的編組行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除