英文:
Go and custom struct type in another struct
问题
我正在努力理解如何在另一个结构体中保存自定义结构体(以及其他很多事情)。目前我的代码看起来是这样的:
type dogs struct {
bleeh string
blaah string
bluuh string
}
type Stuff struct {
collection *mgo.Collection
//myAnimalStruct 这里应该是什么类型?
}
func NewStuff(c *mgo.Collection) *Stuff {
return &Stuff{
collection: c
}
}
func getAll(s *Stuff) interface{} {
collection = s.collection
var results []dogs
err := collection.Find(bson.M{}).All(&results)
if err != nil {
panic(err)
}
return results
}
现在,我想摆脱getAll
函数中的var results []dogs
。相反,我想从我的Stuff
结构体中获取[]dogs
部分,但我无法弄清楚如何做到。
这是我调用这个函数的方式:
func getMeDogs(w http.ResponseWriter, r *http.Request) interface{} {
collection = Collection("animals")
s := NewStuff(collection)
return getAll(s)
}
那么,我如何在Stuff
结构体中做类似s := NewStuff(collection, dogs)
这样的事情,而不需要在Stuff
中将其声明为dogs
类型(它可以是任何类型,在另一个函数中可能是cats
)?
关键是我想重用这个getAll
函数,用于其他类型,而不是为我所有的63种动物编写几乎相同的getAll
函数。喵。
英文:
I'm struggling to understand how to save a custom struct in another struct (amongst great many other things). Currently my code looks like this:
type dogs struct {
bleeh string
blaah string
bluuh string
}
type Stuff struct {
collection *mgo.Collection
//myAnimalStruct what type comes here?
}
func NewStuff(c *mgo.Collection) *Stuff {
return &Stuff{
collection: c
}
}
func getAll(s *Stuff) interface{} {
collection = s.collection
var results []dogs
err := collection.Find(bson.M{}).All(&results)
if err != nil {
panic(err)
}
return results
}
Now, I would like to get rid of that var results []dogs in getAll function. Instead, I would like to get that []dogs bit from my Stuff struct somehow, but I can't figure out how.
this is how I call this function:
func getMeDogs(w http.ResponseWriter, r *http.Request) interface{} {
collection = Collection("animals")
s := NewStuff(collection)
return getAll(s)
}
So how could I do something like s := NewStuff(collection, dogs) to my Stuff struct without declaring it as a dog type in Stuff (it could be anything, in another function it could be cats for all I know...)?
The point is that I want to reuse this getAll function for whatever other types, instead of making nearly identical getAll function for all of my 63 animals. Meow.
答案1
得分: 3
你可以在Stuff中存储类型的原型值,并使用反射创建指向该类型值的指针。
type Stuff struct {
collection *mgo.Collection
v interface{} // 类型的原型值
}
func NewStuff(c *mgo.Collection, v interface{}) *Stuff {
return &Stuff{
collection: c,
v: v,
}
}
func getAll(s *Stuff) (interface{}, error) {
p := reflect.New(reflect.TypeOf(s.v))
if err := s.collection.Find(bson.M{}).All(p.Interface()); err != nil {
return nil, err
}
return p.Elem().Interface(), nil
}
要构建一个Dog集合:
s := NewStuff(collection, []Dog{})
有些人会说反射很慢。这是真的,但在这种情况下,与执行Find().All()的成本相比,成本很小。调用Find().All()会向数据库服务器发送请求并等待响应。服务器的响应使用Mgo的BSON解码器进行解包。BSON解码器大量使用了反射。
英文:
You can store a prototypical value of the type in Stuff and use reflection to create a pointer to a value of that type.
type Stuff struct {
collection *mgo.Collection
v interface{} // the prototype value
}
func NewStuff(c *mgo.Collection, v interface{}) *Stuff {
return &Stuff{
collection: c,
v: v,
}
}
func getAll(s *Stuff) (interface{}, error) {
p := reflect.New(reflect.TypeOf(s.v))
if err := s.collection.Find(bson.M{}).All(p.Interface()); err != nil {
return nil, err
}
return p.Elem().Interface(), nil
}
To construct a Dog collection:
s := NewStuff(collection, []Dog{})
Some people will say that reflection is slow. That's true, but in this case the cost is small compared to the cost of executing Find().All(). The call to Find().All() sends a request to the database server and waits for the response. The response from the server is unpacked using Mgo's BSON decoder. The BSON decoder makes heavy use of reflection.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论