0

我有几个结构、产品和类别。我在下面列出了 2 个函数,它们具有相同的逻辑,只是使用和返回的结构不同。无论如何我可以抽象出结构数据类型并在一个名为的函数中使用相同的逻辑GetObjects吗?

func GetCategories(collection *mongo.Collection) []Category {
    ctx := context.Background()
    cats := []Category{}
    cur, err := collection.Find(ctx, bson.M{})
    if err != nil {
        log.Fatal("Error: ", err)
    }
    for cur.Next(context.TODO()) {
        var cat Category
        err = cur.Decode(&cat)
        if err != nil {
            log.Fatal(err)
        }
        cats = append(cats, cat)
    }
    return cats
}

func GetProducts(collection *mongo.Collection) []Product {
    ctx := context.Background()
    prods := []Product{}
    cur, err := collection.Find(ctx, bson.M{})
    if err != nil {
        log.Fatal("Error: ", err)
    }
    for cur.Next(context.TODO()) {
        var prod Product
        err = cur.Decode(&prod)
        if err != nil {
            log.Fatal(err)
        }
        prods = append(prods, prod)
    }
    return prods
}
4

1 回答 1

4

GetObjs()如果您将传入您希望加载结果的目的地,您可以创建一个概化。

就像是:

func GetObjs(c *mongo.Collection, dst interface{})

调用者负责传递准备好的切片或指向将存储结果的切片变量的指针。

另请注意,context.Context应该在函数内部传递而不是任意创建:

func GetObjs(ctx context.Context, c *mongo.Collection, dst interface{})

此外,应该返回错误而不是“吞下”错误,因此如果发生错误,可以在调用者处适当处理:

func GetObjs(ctx context.Context, c *mongo.Collection, dst interface{}) error

此外,如果您需要所有结果,则无需遍历它们并逐一解码。只需使用Cursor.All().

这就是“改进”的GetObjs()样子:

func GetObjs(ctx context.Context, c *mongo.Collection, dst interface{}) error {
    cur, err := c.Find(ctx, bson.M{})
    if err != nil {
        return err
    }
    return cur.All(ctx, dst)
}

(虽然这变得非常简单,但不确定它是否保证它自己的存在。)

这就是您可以使用它的方式:

ctx := ... // Obtain context, e.g. from the request: r.Context()
c := ... // Collection you want to query from

var cats []Category
if err := GetObjs(ctx, c, &cats); err != nil {
    // Handle error
    return
}
// Use cats

var prods []Product
if err := GetObjs(ctx, c, &prods); err != nil {
    // Handle error
    return
}
// Use prods
于 2020-02-03T12:59:04.153 回答