Я только что прочитал статью: Создайте собственную веб-инфраструктуру на 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}
//....
}
Все работает и обработчики загружаются быстрее, чем при использовании gorilla/context Итак, мои вопросы:
- Безопасен ли этот подход?
- Действительно ли необходимо откладывать функцию c.cancel() так, как я это делаю?
- Могу ли я использовать его для реализации пользовательской веб-инфраструктуры с использованием таких контроллеров, как struct, для обмена значениями с моделями?