将结构组合传递给函数

Passing struct composites into function

需要一些帮助来理解 golang。

来自使用基数的 C++ class 这是微不足道的。在 Go 中,使用结构组合,直到我需要具有采用“Base”结构的函数为止,它都可以正常工作。我知道它不是真正的基础 class,但是当从派生的基础 class 的字段中分配值时,它工作正常。但是我无法将 Dog 传递给采用 Wolf.

的函数
package main
    
import "fmt"
    
type Wolf struct {
    ID     string
    Schema int
}
    
type Dog struct {
    Wolf
}
    
type Dingo struct {
    Wolf
}
    
func processWolf(wolf Wolf) {
    fmt.Println(wolf.ID, wolf.Schema)
}
    
func main() {
    porthos := Dog{}
    porthos.ID = "Porthos"  // works fine able to set field of Wolf
    porthos.Schema = 1      // works fine
    
    aussie := Dingo{}
    aussie.ID = "Aussie"  // works fine
    aussie.Schema = 1     // works fine
    
    fmt.Println(porthos.ID, porthos.Schema)
    fmt.Println(aussie.ID, aussie.Schema)

    processWolf(porthos) << fails here
    processWolf(aussie) << fails here
    
}

processWolf函数接受一个Wolf参数,所以你必须传递一个Wolf。由于两个结构中都嵌入了 Wolf,您可以这样做:

processWolf(porthos.Wolf) 
processWolf(aussie.Wolf) 

因为当你将 Wolf 嵌入到 Dog 中时,Dog 获得了 Wolf 的所有方法,加上 Dog 有一个名为 [=12 的成员=].

当我最初发布这个问题时,我试图简化问题陈述,也许太多了,Serdar 先生很友好地回答了这个问题,但对我的问题没有帮助。在深入研究了 gophers 的语言之后,我遇到了一个使用 interface{} 来解决这个问题的解决方案。我对它进行了改编我的 mongo 代码并且它正在工作,尽管我可能会说它看起来不像其他语言那样简单传递引用。

// FindAll retrieves one object from the collection
func FindAll(collection *mongo.Collection, filter bson.M, resultSet interface{}) error {

    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Seconds)
    defer cancel()

    cursor, err := collection.Find(ctx, filter)
    if err != nil {
        return err
    }

    defer cursor.Close(ctx)

    objects := reflect.ValueOf(resultSet).Elem()

    for cursor.Next(ctx) {

        obj := reflect.New(objects.Type().Elem())

        err = cursor.Decode(obj.Interface())

        if err != nil {
            log.Panicln("FindAll:", err.Error())
            // assuming that an interface is out of alignment and need to know ASAP.
        }

        objects = reflect.Append(objects, obj.Elem())
    }

    reflect.ValueOf(resultSet).Elem().Set(objects)

    return nil
}

然后使用

调用它
    var dogs []Dog
    if err := database.FindAll(houseCollection, bson.M{}, &dogs); err != nil {
        return nil, err
    }

    println(dogs)
    var dingos []Dingo
    if err := database.FindAll(houseCollection, bson.M{}, &dingos); err != nil {
        return nil, err
    }

    println(dingos)

没有 Dog 和 Dingo 必须与基地相关 class。但是我真的觉得Golang的设计者做了一些我还没有理解的奇怪的转折。虽然追地鼠很开心。