我正在创建一个 API,我有两种不同的 JSON 响应结构;一种用于单个记录,一种用于收集记录:
type Model struct {
Id uint
}
type Collection struct {
Records []Model
}
Model
只是数据库数据(例如,用户)的结构表示,Collection
是模型的集合。
问题是会有单独的结构嵌入 Model
类型,如下所示:
type User struct {
*Model
Name string
}
因为 User
不满足 Model
类型,我不能像这样将它附加到 Collection
结构中:
user := User{&Model{1}, "Jon"}
uc := &Collection{[]User{user}}
如何让 Records 结构接受实现 Model
的结构类型?
最佳答案
你有两个选择:
- 创建另一种集合类型
- 改用接口(interface)
如果您没有太多的 foos 和 bars,可以选择实现单独的集合,例如 UserCollection
、BarCollection
、FooCollection
。
另一种方法是使用通用的空接口(interface)类型 interface{}
,它将保存任何类型的值(因为每种类型的每个实例都满足空接口(interface)):
type Collection struct {
Records []interface{}
}
这有很多缺点,例如每次访问 Records
字段时都必须进行类型断言,您可能会错误地将所有内容放在那里,并且您必须使用反射进行大多数操作。
使用接口(interface)的更好方法是实现一个模型接口(interface),并让作为模型的每个类型都实现该接口(interface):
type Model interface {
ImplementsModel()
}
type BaseModel struct {
Id uint
}
func (b *BaseModel) ImplementsModel() {}
type User struct {
*BaseModel
Name string
}
type Collection struct {
Records []Model
}
当然,一旦有了有意义的方法,您就可以删除 ImplementsModel
虚拟方法。这个虚拟方法只是用来区分接口(interface)和空接口(interface),这样你就不能将整数值或字符串代替实际模型放入集合中。
关于struct - 嵌入式类型和结构的多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32981576/