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 关注
- 447 浏览
添加回答
举报