为了账号安全,请及时绑定邮箱和手机立即绑定

正确使用 go context.Context

正确使用 go context.Context

Go
ibeautiful 2021-10-18 11:03:51
我刚刚阅读了这篇文章:在 Go 中构建您自己的 Web 框架,为了在处理程序之间共享值,我选择了context.Context并以以下方式使用它来跨处理程序和中间件共享值:type appContext struct {    db     *sql.DB    ctx    context.Context    cancel context.CancelFunc }func (c *appContext)authHandler(next http.Handler) http.Handler {    fn := func(w http.ResponseWriter, r *http.Request {        defer c.cancel() //this feels weird        authToken := r.Header.Get("Authorization") // this fakes a form        c.ctx = getUser(c.ctx, c.db, authToken) // this also feels weird        next.ServeHTTP(w, r)    }    return http.HandlerFunc(fn)}func (c *appContext)adminHandler(w http.ResponseWriter, r *http.Request) {    defer c.cancel()    user := c.ctx.Value(0).(user)    json.NewEncoder(w).Encode(user)}func getUser(ctx context.Context, db *sql.DB, token string) context.Context{    //this function mimics a database access    return context.WithValue(ctx, 0, user{Nome:"Default user"})}func main() {    db, err := sql.Open("my-driver", "my.db")    if err != nil {        panic(err)    }    ctx, cancel := context.WithCancel(context.Background())    appC := appContext{db, ctx, cancel}    //....}一切正常,处理程序的加载速度比使用 gorilla/context 快所以我的问题是:这种方法安全吗?真的有必要按照我的方式推迟 c.cancel() 函数吗?我可以使用它来实现自定义 Web 框架,通过使用 struct 之类的控制器与模型共享值吗?
查看完整描述

3 回答

?
慕哥9229398

TA贡献1877条经验 获得超6个赞

注意:go 1.7.0-rc2 确实阐明了如何释放与上下文相关的资源(Sameer Ajmani):

一些用户没有意识到Context用 a创建 aCancelFunc会将子树附加到父级,并且在CancelFunc调用 或取消父级之前不会释放该子树

在包文档中尽早明确这一点,以便人们了解这个包有正确的概念模型。

该文档现在包括:

对服务器的传入请求应创建Context,而对服务器的传出调用应接受Context.
它们之间的函数调用链必须传播Context,可选择将其替换为Context使用WithCancelWithDeadlineWithTimeout、 或 所创建的派生WithValue
这些Context值形成一棵树:当 aContext被取消时,所有Contexts从它派生的也被取消

WithCancelWithDeadlineWithTimeout函数返回一个派生ContextCancelFunc
调用CancelFunc取消新的Context和从它派生的任何上下文,Context从父树的树中删除,并停止任何相关的计时器。在父级被取消或计时器触发之前,
未能调用CancelFunc泄漏相关资源Context


查看完整回答
反对 回复 2021-10-18
  • 3 回答
  • 0 关注
  • 227 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信