从父方法访问所有字段
Access all fields from parent method
我正在开发一个将数据存储在 mongodb 中的应用程序。有几个集合,当然它们都有一些共同的字段(如 Id、创建日期等)和方法(例如 Insert)。在我的设想中,我需要创建具有所需字段和方法的基本模型结构,然后将此结构嵌入到我的模型中。不幸的是,这不起作用,因为为基本模型定义的方法看不到子字段。
我不知道如何进一步解释。这是操场上的代码:
https://play.golang.org/p/_x-B78g4TV
用的是json而不是mgo,但是思路还是一样的
我希望输出为:
Saving to 'my_model_collection'
{"_id":42, "foo": "Some value for foo", "bar": "Here we set some value for bar"}
不是:
Saving to 'my_model_collection'
{"_id":42}
为我的每个模型编写插入方法似乎有悖于 DRY,那么 correct/idiomatic 在 Go 中实现这一点的方法是什么?
众所周知的问题;o) 名称以小写字母开头的成员变量(如 collectionName)在其他包中不可见(如 json)。因此将结构更改为:
type BaseModel struct {
Id int `json:"_id"`
CollectionName string `json:"collectionName"`
}
世界将变得更适合居住。
在 Golang 中,您不能覆盖父方法,因为多态性不是这样工作的。 Insert
方法将应用于 BaseModel
成员,而不是 MyModel
.
此外,您试图以不正确的方式使用 mgo。如果你想在集合中插入文档,那么你已经有一个 Collection
结构的 Insert
方法,它适用于 interface{}
类型(与 json.Marshal
相同)。
当然,您可以有一个 BaseModel
来包含所有模型共享的字段。事实上,GORM 使用了类似的方法并提供了一个 Model
结构体来包含在每个子模型中。
这个不行,具体看我的回答:Can embedded struct method have knowledge of parent/child?
你可以做两件事:
1。放弃方法并使其成为辅助/实用函数
想法是让Insert()
从BaseModel
中分离出来,使它成为一个简单的函数,然后将要保存的文档传递给它。
我个人更喜欢这个选项,因为它需要更少的麻烦和维护。它可能看起来像这样:
func Insert(doc interface{}) {
j, _ := json.Marshal(doc)
fmt.Println(string(j))
}
您在标签中也有一个 "typo":
type MyModel struct {
*BaseModel
Foo string `json:"foo"`
Bar string `json:"bar"`
}
使用它:
Insert(m)
输出(在 Go Playground 上尝试):
{"_id":42,"foo":"Some value for foo","bar":"Here we set some value for bar"}
2。将包装器(指向)传递给 BaseModel
在这种方法中,您必须传递一个指向嵌入器结构的指针,这样 BaseModel.Insert()
方法就会有一个指向它的指针,并且可以使用它来保存/编组。这基本上是手动维护嵌入我们的结构的 "reference" 并且正在 saved/marshalled.
这是它的样子:
type BaseModel struct {
Id int `json:"_id"`
collectionName string
wrapper interface{}
}
然后在 Insert()
方法中保存 wrapper
:
func (m *BaseModel) Insert() {
fmt.Printf("Saving to '%v'\n", m.collectionName)
j, _ := json.Marshal(m.wrapper)
fmt.Println(string(j))
}
创建稍微复杂一点:
func NewMyModel() *MyModel {
mm := &MyModel{
Foo: "Some value for foo",
}
mm.BaseModel = NewBaseModel("my_model_collection", mm)
return mm
}
但输出如你所愿:
Saving to 'my_model_collection'
{"_id":42,"foo":"Some value for foo","bar":"Here we set some value for bar"}
在 Go Playground 上试用。
我正在开发一个将数据存储在 mongodb 中的应用程序。有几个集合,当然它们都有一些共同的字段(如 Id、创建日期等)和方法(例如 Insert)。在我的设想中,我需要创建具有所需字段和方法的基本模型结构,然后将此结构嵌入到我的模型中。不幸的是,这不起作用,因为为基本模型定义的方法看不到子字段。
我不知道如何进一步解释。这是操场上的代码: https://play.golang.org/p/_x-B78g4TV
用的是json而不是mgo,但是思路还是一样的
我希望输出为:
Saving to 'my_model_collection'
{"_id":42, "foo": "Some value for foo", "bar": "Here we set some value for bar"}
不是:
Saving to 'my_model_collection'
{"_id":42}
为我的每个模型编写插入方法似乎有悖于 DRY,那么 correct/idiomatic 在 Go 中实现这一点的方法是什么?
众所周知的问题;o) 名称以小写字母开头的成员变量(如 collectionName)在其他包中不可见(如 json)。因此将结构更改为:
type BaseModel struct {
Id int `json:"_id"`
CollectionName string `json:"collectionName"`
}
世界将变得更适合居住。
在 Golang 中,您不能覆盖父方法,因为多态性不是这样工作的。 Insert
方法将应用于 BaseModel
成员,而不是 MyModel
.
此外,您试图以不正确的方式使用 mgo。如果你想在集合中插入文档,那么你已经有一个 Collection
结构的 Insert
方法,它适用于 interface{}
类型(与 json.Marshal
相同)。
当然,您可以有一个 BaseModel
来包含所有模型共享的字段。事实上,GORM 使用了类似的方法并提供了一个 Model
结构体来包含在每个子模型中。
这个不行,具体看我的回答:Can embedded struct method have knowledge of parent/child?
你可以做两件事:
1。放弃方法并使其成为辅助/实用函数
想法是让Insert()
从BaseModel
中分离出来,使它成为一个简单的函数,然后将要保存的文档传递给它。
我个人更喜欢这个选项,因为它需要更少的麻烦和维护。它可能看起来像这样:
func Insert(doc interface{}) {
j, _ := json.Marshal(doc)
fmt.Println(string(j))
}
您在标签中也有一个 "typo":
type MyModel struct {
*BaseModel
Foo string `json:"foo"`
Bar string `json:"bar"`
}
使用它:
Insert(m)
输出(在 Go Playground 上尝试):
{"_id":42,"foo":"Some value for foo","bar":"Here we set some value for bar"}
2。将包装器(指向)传递给 BaseModel
在这种方法中,您必须传递一个指向嵌入器结构的指针,这样 BaseModel.Insert()
方法就会有一个指向它的指针,并且可以使用它来保存/编组。这基本上是手动维护嵌入我们的结构的 "reference" 并且正在 saved/marshalled.
这是它的样子:
type BaseModel struct {
Id int `json:"_id"`
collectionName string
wrapper interface{}
}
然后在 Insert()
方法中保存 wrapper
:
func (m *BaseModel) Insert() {
fmt.Printf("Saving to '%v'\n", m.collectionName)
j, _ := json.Marshal(m.wrapper)
fmt.Println(string(j))
}
创建稍微复杂一点:
func NewMyModel() *MyModel {
mm := &MyModel{
Foo: "Some value for foo",
}
mm.BaseModel = NewBaseModel("my_model_collection", mm)
return mm
}
但输出如你所愿:
Saving to 'my_model_collection'
{"_id":42,"foo":"Some value for foo","bar":"Here we set some value for bar"}
在 Go Playground 上试用。