ここでは、主にリクエストのコンテキストを紹介しますが、注意点がいくつかあります。ミドルウェアを使用する場合は、すべてのリクエストを処理する必要があります。これは必要ですか?respのwritetimeoutにも注意してください。それ以外の場合、SQL処理でのリクエストのタイムアウトがwよりも大きい場合、それは基本的に無効です。
処理されません、まず条件付きSQLを作成します
メインパッケージ のインポート( " データベース/ SQL " " FMT " " ログ" " ネット/ HTTP " _ " github.com/lib/pq " ) のvarデシベル* sql.DB FUNC slowQuery()エラー{ :_、ERR =デシベルを。 Exec(" SELECT pg_sleep(10)" ) return err } func main(){ var err error db、err = sql.Open(" postgres "、" postgres:// user:pa $$ word @ localhost / example_db" ) if err!= nil { log.Fatal(err) } if err = db.Ping(); err!= nil { log.Fatal(err) } mux: = http.NewServeMux() mux.HandleFunc(" / " 、exampleHandler) log.Println(" Listening ... " ) err = http.ListenAndServe(" :5000 " 、mux) if err!= nil { log.Fatal(err) } } func exampleHandler(w http.ResponseWriter、 r* http.Request){ err: = slowQuery() if err!= nil { serverError(w、err) return } fmt.Fprintln(w、" OK " ) } func serverError(w http.ResponseWriter、err error){ ログ.Printf(" ERROR:%s " 、err.Error()) http.Error(w、" 申し訳ありませんが、問題が発生しました" 、http.StatusInternalServerError) }
いくつかの処理デモ
メインパッケージ のインポート( " 文脈" // 新しいインポート " データベース/ SQL " " FMT " " ログ" " ネット/ HTTP " " 時間" // 新しいインポート _ " github.com/lib/pq " ) のvarデシベル* SQLを。 DB func slowQuery(ctx context.Context)error { // 指定されたctxパラメータを親として使用して、// 5秒のタイムアウトで新しい子コンテキストを作成します 。 ctx、キャンセル:= context.WithTimeout(ctx、time.Second)は 延期)(キャンセル // 最初と子コンテキスト(タイムアウト付き1)を渡し // )ExecContext(へのパラメータ。 _、err:= db.ExecContext(ctx、" SELECT pg_sleep(10)" ) return err } ... func exampleHandler(w http.ResponseWriter、r * http.Request){ // リクエストコンテキストをslowQuery()に渡すなので、// 親コンテキストとして使用でき ます。 err:= slowQuery(r.Context()) if if err!= nil { serverError(w、err) return } fmt.Fprintln(w、" OK " ) } ...
パッケージのメイン インポート( " 文脈" " データベース/ SQL " " エラー" // 新しいインポート " FMT " " ログ" " ネット/ HTTP " " 時間" _ " github.com/lib/pq " ) のvarデシベル* sql.DB func slowQuery(ctx context.Context)error { ctx、cancel: = context.WithTimeout(ctx、5 * time.Second) defer cancel() _、err: = db.ExecContext(ctx、」SELECT pg_sleep(10)" ) // "とのエラーラップ、それをキャンセルする声明...:PQ我々は、取得する場合は、" // 返す前に、コンテキスト・エラーを。 もし ERR = nilの&& err.Error()==!" PQ:ユーザー要求によるステートメントのキャンセル" { return fmt.Errorf(" %w:%v " 、ctx.Err()、err) } return err } ... func exampleHandler(w http.ResponseWriter、r * http.Request) { err: = slowQuery(r.Context()) if err!= nil { //返されたエラーがcontext.Canceledと等しいかラップするかどうかを確認し、// 等しい場合は 警告を記録します。 スイッチ{ case errors.Is(err、context.Canceled): serverWarning(err) default : serverError(w、err) } return } fmt.Fprintln(w、" OK " ) } func serverWarning(err error){ log.Printf (" 警告:%s " 、err.Error()) } ...
... func main(){ var err error db、err = sql.Open(" postgres "、" postgres:// user:pa $$ word @ localhost / example_db " ) if err!= nil { log.Fatal( ERR) } // 空用い、10秒のタイムアウトを有するコンテキストを作成 // 親としてcontext.Backgroundを()。 ctx、cancel:= context.WithTimeout(context.Background()、10 * time.Second) defer cancel() // 接続プールをテストするときにこれを使用します。 もしエラー= db.PingContext(ctx); err!= nil { log.Fatal(err) } mux: = http.NewServeMux() mux.HandleFunc(" / " 、exampleHandler) log.Println(" Listening ... " ) err = http.ListenAndServe(" :5000 " 、mux) if err!= nil { log.Fatal(err) } } ...
ミドルウェア
func setTimeout(next http.Handler)http.Handler { return http.HandlerFunc(func(w http.ResponseWriter、r * http.Request){ ctx、cancel: = context.WithTimeout(r.Context()、5 * time。第二) )(取り消し延期 // これは、要求コンテキストであなたの要求のコピーを提供します // 作成した5秒のタイムアウトを新しいコンテキストに変更 // 上記の。 R = r.WithContext(CTX) next.ServeHTTP (w、r) }) }
元の住所
https://www.alexedwards.net/blog/how-to-manage-database-timeouts-and-cancellations-in-go
著者は非常に詳細に書いた、内容は難しくありません。