在另一个结构体中使用和自定义结构类型。

huangapple go评论112阅读模式
英文:

Go and custom struct type in another struct

问题

我正在努力理解如何在另一个结构体中保存自定义结构体(以及其他很多事情)。目前我的代码看起来是这样的:

  1. type dogs struct {
  2. bleeh string
  3. blaah string
  4. bluuh string
  5. }
  6. type Stuff struct {
  7. collection *mgo.Collection
  8. //myAnimalStruct 这里应该是什么类型?
  9. }
  10. func NewStuff(c *mgo.Collection) *Stuff {
  11. return &Stuff{
  12. collection: c
  13. }
  14. }
  15. func getAll(s *Stuff) interface{} {
  16. collection = s.collection
  17. var results []dogs
  18. err := collection.Find(bson.M{}).All(&results)
  19. if err != nil {
  20. panic(err)
  21. }
  22. return results
  23. }

现在,我想摆脱getAll函数中的var results []dogs。相反,我想从我的Stuff结构体中获取[]dogs部分,但我无法弄清楚如何做到。

这是我调用这个函数的方式:

  1. func getMeDogs(w http.ResponseWriter, r *http.Request) interface{} {
  2. collection = Collection("animals")
  3. s := NewStuff(collection)
  4. return getAll(s)
  5. }

那么,我如何在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:

  1. type dogs struct {
  2. bleeh string
  3. blaah string
  4. bluuh string
  5. }
  6. type Stuff struct {
  7. collection *mgo.Collection
  8. //myAnimalStruct what type comes here?
  9. }
  10. func NewStuff(c *mgo.Collection) *Stuff {
  11. return &Stuff{
  12. collection: c
  13. }
  14. }
  15. func getAll(s *Stuff) interface{} {
  16. collection = s.collection
  17. var results []dogs
  18. err := collection.Find(bson.M{}).All(&results)
  19. if err != nil {
  20. panic(err)
  21. }
  22. return results
  23. }

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:

  1. func getMeDogs(w http.ResponseWriter, r *http.Request) interface{} {
  2. collection = Collection("animals")
  3. s := NewStuff(collection)
  4. return getAll(s)
  5. }

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中存储类型的原型值,并使用反射创建指向该类型值的指针。

  1. type Stuff struct {
  2. collection *mgo.Collection
  3. v interface{} // 类型的原型值
  4. }
  5. func NewStuff(c *mgo.Collection, v interface{}) *Stuff {
  6. return &Stuff{
  7. collection: c,
  8. v: v,
  9. }
  10. }
  11. func getAll(s *Stuff) (interface{}, error) {
  12. p := reflect.New(reflect.TypeOf(s.v))
  13. if err := s.collection.Find(bson.M{}).All(p.Interface()); err != nil {
  14. return nil, err
  15. }
  16. return p.Elem().Interface(), nil
  17. }

要构建一个Dog集合:

  1. 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.

  1. type Stuff struct {
  2. collection *mgo.Collection
  3. v interface{} // the prototype value
  4. }
  5. func NewStuff(c *mgo.Collection, v interface{}) *Stuff {
  6. return &Stuff{
  7. collection: c,
  8. v: v,
  9. }
  10. }
  11. func getAll(s *Stuff) (interface{}, error) {
  12. p := reflect.New(reflect.TypeOf(s.v))
  13. if err := s.collection.Find(bson.M{}).All(p.Interface()); err != nil {
  14. return nil, err
  15. }
  16. return p.Elem().Interface(), nil
  17. }

To construct a Dog collection:

  1. 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.

huangapple
  • 本文由 发表于 2014年9月10日 22:59:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/25768783.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定