我刚刚阅读了文章:Build You Own Web Framework In Go并且为了在处理程序之间共享值,我选择了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}
//....
}
一切正常,处理程序加载速度比使用大猩猩/上下文更快所以我的问题是:
答案 0 :(得分:1)
您的代码存在问题,因为您将用户存储到应用程序上下文中。同时有多个用户,它不起作用。上下文必须与不被其他请求覆盖的请求相关。用户必须存储在请求上下文中。在我的文章中,我使用以下大猩猩函数:p
。 context.Set(r, "user", user)
是请求。
如果您想在应用中使用r
,则应使用他们的大猩猩包装器(您可以在本文末尾找到它:https://blog.golang.org/context)。
此外,您不需要具有取消的上下文。 context.Context
可以用于根上下文。
答案 1 :(得分:1)
注意:去1.7.0-rc2确实澄清了一点how to release resources associated with Contexts(Sameer Ajmani):
有些用户没有意识到创建
Context
并CancelFunc
将子树附加到父级,并且该子树在CancelFunc
之前不会被释放被叫或父母被取消。在软件包文档的早期明确说明,以便了解此软件包的人员具有正确的概念模型。
对服务器的传入请求应创建
Context
,对服务器的传出呼叫应接受Context
。
它们之间的函数链调用必须传播Context
,可选地将其替换为使用Context
,WithCancel
,WithDeadline
或{{WithTimeout
创建的派生WithValue
。 1}}。
这些Context
值组成了一个树:取消Context
时,从中导出的所有Contexts
也会被取消。
WithCancel
,WithDeadline
和WithTimeout
函数会返回派生的Context
和CancelFunc
。
调用CancelFunc
取消新的Context
以及从中派生的任何上下文,从父树中删除Context
,并停止所有关联的计时器。
未能调用CancelFunc
会泄漏相关资源,直到取消父Context
或计时器触发。
答案 2 :(得分:0)
Context包的两个主要用例是:
使用上下文将以context.Background()为根的上下文树形成。 WithValue(),context.WithCancel(),WithTimeout(),WithDeadline()是从根上下文派生的上下文,可以进一步划分。每个示例都可以使您清楚地知道什么是正确的使用上下文。查阅了本指南,该指南提供了上面讨论的所有内容的使用以及适当的示例。
来源:https://golangbyexample.com/using-context-in-golang-complete-guide/