3

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}
    //....
}

すべてが機能しており、ゴリラ/コンテキストを使用するよりもハンドラーの読み込みが高速です。私の質問は次のとおりです。

  1. このアプローチは安全ですか?
  2. 私がやっているように c.cancel() 関数を延期することは本当に必要ですか?
  3. 構造体などのコントローラーを使用してモデルと値を共有することで、カスタム Web フレームワークを実装するために使用できますか?
4

3 に答える 3

1

ユーザーをアプリ コンテキストに格納しているため、コードに問題があります。同時に複数のユーザーがいる場合、機能しません。コンテキストは、他のリクエストによって上書きされないように、リクエストに関連している必要があります。ユーザーはリクエストコンテキストに保存する必要があります。私の記事では、次のゴリラ関数を使用しています: context.Set(r, "user", user). rリクエストです。

アプリで使用するcontext.Context場合は、ゴリラ ラッパーを使用する必要があります (この記事の最後に記載されています: https://blog.golang.org/context )。

また、キャンセルのコンテキストは必要ありません。context.Background()ルートコンテキストでは問題ありません。

于 2015-06-19T05:02:35.010 に答える