【发布时间】:2022-08-16 14:20:50
【问题描述】:
我目前正在将事务逻辑集成到我的 go+mongodb api 中。
我已经创建了这个示例端点。它允许您检索用户文档并使用 json 编码将其发送回客户端。
func GetUser(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)[\"user-id\"]
objectId, _ := primitive.ObjectIDFromHex(id)
user, err := UserById(objectId)
if err != nil {
// ...
}
// do some stuff with the user, whatever
// eventually send it back
json.NewEncoder(w).Encode(user)
}
func UserById(id primitive.ObjectID) (models.StoredUser, error) {
session, err := mongoClient.StartSession()
if err != nil {
return models.StoredUser{}, fmt.Errorf(\"failed starting session for transaction | %s\", err.Error())
}
defer session.EndSession(context.TODO())
callback := func(ctx mongo.SessionContext) (any, error) {
res := usersCollection.FindOne(
ctx,
bson.M{
\"_id\": id,
},
)
if res.Err() != nil {
return models.StoredUser{}, fmt.Errorf(\"failed querying db | %s\", res.Err())
}
return res, nil
}
result, err := session.WithTransaction(context.TODO(), callback)
if err != nil {
return models.StoredUser{}, fmt.Errorf(\"failed executing transaction | %s\", err.Error())
}
asserted := result.(*mongo.SingleResult)
var ret models.StoredUser
if err := asserted.Decode(&ret); err != nil {
return models.StoredUser{}, fmt.Errorf(\"failed parsing user data in struct | %s\", err.Error())
}
return ret, nil
}
以下是主要步骤:
- 解析请求内容获取用户id
- 创建会话以执行事务
- 使用 id 参数声明回调函数
- 从事务调用回调函数
- 取回
*mongo.SingleResult作为interface{}并将其解析回其原始类型 - 解码
*mongo.SingleResult中包含的bson文档,放入return struct此函数有效,但非常冗长。代码非常重复。
我想知道是否有一种方法可以不为我想要制作的每个功能重复相同的代码。我之前的包装函数尝试没有产生任何结果,因为我实际上需要它们现在在每次调用时所在的变量。
尽管如此,第 2 步和第 5 步似乎显得非常多余和低效。
有人知道吗?
标签: mongodb go transactions