亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何解析 YAML 文件并從父結構創建子對象(繼承)

如何解析 YAML 文件并從父結構創建子對象(繼承)

Go
catspeake 2022-05-05 17:53:55
假設我有以下結構:type CarShop struct {  Cars []*Car}type Car struct {  ID string `yaml:“id“`}type BMW struct {  Car  A string `yaml:“a“`}type Mercedes struct {  Car  B string `yaml:“b“}我想解析以下字符串:- BMW:    id: ?BMW“    a: ?a“- Mercedes:    id: ?Mercedes“    b: ?b“我需要做什么才能動態創建解析此字符串的 BMW 和 Mercedes 對象?這甚至可以使用 Go 和 go-yaml 嗎?
查看完整描述

1 回答

?
斯蒂芬大帝

TA貢獻1827條經驗 獲得超8個贊

您的類型錯誤,Go 沒有繼承。您不能將類型的值存儲到類型*Mercedes的*BMW數組中[]*Car;兩種類型都只包含一個Car值作為 mixin。要做你想做的事,你必須把你的Car類型變成一個界面。


現在是 YAML 部分:您可以將 YAML 結構的一部分存儲在一個類型的對象中,yaml.Node然后再對其進行反序列化。您可以通過實現UnmarshalYAML(從yaml.Unmarshaler接口)來實現自定義解組器。所以我們要做的是實現一個自定義解組器,CarShop它將周圍的結構反序列化為一個列表,其中包含從汽車類型到yaml.Node(該類型的值)的映射,然后根據給定的汽車類型,將每個節點反序列化為適當的類型。這是它的外觀:


package main


import (

    "errors"

    "fmt"

    "gopkg.in/yaml.v3"

)


type CarShop struct {

    Cars []Car

}


type Car interface {

    ID() string

}


type BMW struct {

    IDVal string `yaml:"id"`

    A     string `yaml:"a"`

}


func (bmw *BMW) ID() string {

    return bmw.IDVal

}


type Mercedes struct {

    IDVal string `yaml:"id"`

    B     string `yaml:"b"`

}


func (merc *Mercedes) ID() string {

    return merc.IDVal

}


type tmpCarShop []map[string]yaml.Node


func (cs *CarShop) UnmarshalYAML(value *yaml.Node) error {

    var tmp tmpCarShop

    if err := value.Decode(&tmp); err != nil {

        return err

    }

    cars := make([]Car, 0, len(tmp))

    for i := range tmp {

        for kind, raw := range tmp[i] {

            switch kind {

            case "Mercedes":

                m := &Mercedes{}

                if err := raw.Decode(m); err != nil {

                    return err

                }

                cars = append(cars, m)

            case "BMW":

                b := &BMW{}

                if err := raw.Decode(b); err != nil {

                    return err

                }

                cars = append(cars, b)

            default:

                return errors.New("unknown car type: " + kind)

            }

        }

    }

    cs.Cars = cars

    return nil

}


func main() {

    input := []byte(`

- BMW:

    id: "BMW"

    a: "a"

- Mercedes:

    id: "Mercedes"

    b: "b"

`)


    var shop CarShop

    if err := yaml.Unmarshal(input, &shop); err != nil {

        panic(err)

    }


    for i := range shop.Cars {

        fmt.Printf("ID: %s\n", shop.Cars[i].ID())

        switch c := shop.Cars[i].(type) {

        case *Mercedes:

            fmt.Printf("Type: Mercedes\nA: %s\n", c.B)

        case *BMW:

            fmt.Printf("Type: BMW\nB: %s\n", c.A)

        }

        fmt.Println("---")

    }

}


查看完整回答
反對 回復 2022-05-05
  • 1 回答
  • 0 關注
  • 519 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號