将动态结构传递给golang中的函数
Passing in dynamic struct into function in golang
我有几个结构,产品和类别。我有下面列出的 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
}
如果您要传递要加载结果的目的地,则可以创建通用的 GetObjs()
。
类似于:
func GetObjs(c *mongo.Collection, dst interface{})
并且调用者负责传递一个就绪的切片或指向将存储结果的切片变量的指针。
还要注意context.Context
要传进去,不要在函数内部任意创建:
func GetObjs(ctx context.Context, c *mongo.Collection, dst interface{})
此外,应该返回错误而不是 "swallowed",因此如果发生错误,可以在调用者处适当处理:
func GetObjs(ctx context.Context, c *mongo.Collection, dst interface{}) error
此外,如果您需要所有结果,则无需遍历它们并逐一解码。只需使用 Cursor.All()
.
这就是 "improved" 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
我有几个结构,产品和类别。我有下面列出的 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
}
如果您要传递要加载结果的目的地,则可以创建通用的 GetObjs()
。
类似于:
func GetObjs(c *mongo.Collection, dst interface{})
并且调用者负责传递一个就绪的切片或指向将存储结果的切片变量的指针。
还要注意context.Context
要传进去,不要在函数内部任意创建:
func GetObjs(ctx context.Context, c *mongo.Collection, dst interface{})
此外,应该返回错误而不是 "swallowed",因此如果发生错误,可以在调用者处适当处理:
func GetObjs(ctx context.Context, c *mongo.Collection, dst interface{}) error
此外,如果您需要所有结果,则无需遍历它们并逐一解码。只需使用 Cursor.All()
.
这就是 "improved" 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