Передача динамической структуры c в функцию в golang - PullRequest
0 голосов
/ 03 февраля 2020

У меня есть пара структур, продуктов и категорий. У меня есть 2 функции, перечисленные ниже, которые имеют идентичные логики c, просто разные структуры, которые используются и возвращаются В любом случае я могу абстрагировать типы данных struct и использовать те же логики c в одной функции под названием 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
}

1 Ответ

3 голосов
/ 03 февраля 2020

Вы можете создать обобщенный 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
...