Editor PHP Zimo berada di sini untuk berkongsi petua tentang cara menggunakan semula struktur dalam pakej pihak ketiga dan menukar gelagat marshalling satu medan. Apabila kami menggunakan pakej pihak ketiga, kadangkala kami perlu menyesuaikan medan di dalamnya. Artikel ini akan memperkenalkan kaedah mudah yang boleh mencapai matlamat ini melalui pewarisan dan timpa ganti, yang bukan sahaja boleh menggunakan semula struktur asal tetapi juga memenuhi keperluan yang diperibadikan. Seterusnya, mari kita lihat kaedah pelaksanaan khusus!
Misalkan saya mahu menyusun struct ke dalam YAML, dan struct itu sudah mempunyai semua teg YAMLnya yang ditakrifkan, kecuali satu yang ingin saya ubah. Bagaimanakah saya boleh mengubah tingkah laku medan tunggal ini tanpa mengubah struktur itu sendiri? Andaikan bahawa struktur datang daripada pakej pihak ketiga.
Berikut ialah contoh untuk ditunjukkan, dan percubaan terbaik saya. Andaikan bahawa User
结构(及其关联的 Secret
struktur) datang daripada pakej pihak ketiga, jadi kami tidak boleh mengubah suainya.
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 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 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) }
Berikut ialah pautan Go Playground untuk kod di atas: https://go.dev/play/p/ojiPv4ylCEq
Ini tidak mungkin.
"Percubaan terbaik" anda ialah jalan yang betul.
Atas ialah kandungan terperinci Bagaimanakah saya boleh menggunakan semula struktur daripada pakej pihak ketiga sambil menukar gelagat marshalling medan individu?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!