我有一个用多个模块编写的Web应用程序,一个与所有数据库相关的事物,一个处理报告,一个人组成了所有Web服务,一个仅用于业务逻辑和数据完整性验证和其他几个。因此,我有许多方法,这些模块已涵盖了功能。
现在,要求是在Web服务中使用会话,以及我们需要在某些API中使用交易。我想到的第一种方法是更改支持会话的现有方法的签名,交易(*sql.tx)(这是一项痛苦的任务,但无论如何都必须做!)。现在,恐怕将来会发生一些需要通过所有这些方法,然后我是否应该再次经过此周期才能再次更改方法签名,该怎么办?这似乎不是一个好方法。
稍后,我发现context.context可能是一种很好的方法(好吧,您也可以建议其他方法,除此之外!),对于每个方法调用,只需在方法呼叫的第一个参数中传递上下文参数,因此我只需更改一次签名的方法。如果我采用这种方法,谁能告诉我如何在该上下文对象中设置/传递多个键(session,sql.tx)?(afaik,context.context提供 WithValue
方法,但是我可以将其用于多个键吗?如何在嵌套函数调用中设置键,甚至可能?)
实际上,这个问题有两个问题:
- 我应该考虑解决方案的
context.Context
吗?如果没有,请给我另一种方法。 - 如何在
context.Context
中设置多个键和值?
对于第二个问题,您可以在struct中分组所有键/值,如下所示:
type vars struct {
lock sync.Mutex
db *sql.DB
}
然后您可以在上下文中添加此结构:
ctx := context.WithValue(context.Background(), "values", vars{lock: mylock, db: mydb})
您可以检索:
ctxVars, ok := r.Context().Value("values").(vars)
if !ok {
log.Println(err)
return err
}
db := ctxVars.db
lock := ctxVars.lock
我希望它对您有帮助。
最后,在研究了GO上下文体验报告中的文章之后,我决定使用上下文包解决方案。尤其是我发现戴夫·切尼(Dave Cheney)的文章很有帮助。
好吧,我可以作为大猩猩(啊,有点!)作为上下文的自定义解决方案。但是由于GO已经有一个解决方案,所以我会选择上下文包。
现在,我只需要每种方法中的会话和数据库事务即可在开始时支持交易,并且用户身份验证,授权。
它可能是开销,在应用程序的每种方法中都有context.Context
,因为我目前不需要取消,截止日期,超时功能,但是将来可能会有所帮助。