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("---")
}
}
- 1 回答
- 0 關注
- 519 瀏覽
添加回答
舉報