2017-08-12 6 views
0

接続プールからデータベースに接続し、クエリを実行して返された結果を処理するサンプル関数を次に示します。defer:長時間実行される関数の場合の使用?

func dbQuery() error { 
    con := db.getConn() 
    result, err := con.Query() 
    if err != nil { 
     return err 
    } 
    defer con.close() // or con.close() 
    // Processing the result takes a long time 


    return nil 
} 

この場合の結果の処理には時間がかかり、接続にはクローズが呼び出されないため、接続プールに返されません。
不要な場合でもリソースが長期間保持されていることがわかっている場合、このような場合にcon.close()を直接呼び出すことはできますか?

答えて

2

ほとんどの場合、Close()メソッドは冪等であり、2回以上安全に呼び出すことができます。あなたはエラーや初期の関数が返ってきた場合にはdefer con.Close()を返しますが、完了したらすぐにClose()に明示的に電話するのは大丈夫です。だから、長い機能を持っているときは両方を使うのがベストプラクティスです。

+0

が、それはのようにreturn文を持つことが理にかなって 'を返しcon.Close()'際多分閉じるによって返されたエラー()? defer con.Close()は、エラー処理の権利を一切許可しません。 –

+0

@AnkitDeshpandeあなたの質問から、私はあなたの長い関数が終了する前にいつか接続を完了すると思います。その時点で、接続を閉じてプールに解放したいと思うでしょう。この仮定を前提にすると、関数を続行する前にエラーをキャプチャして正常にテストするのではなく、エラーが実際に存在する場合のみ返すのではないでしょうか? – RayfenWindspear

+0

@AnkitDeshpande:名前付きのリターンパラメータを使用してdefer関数で値を設定することで、 'defer'から値を返すことができます。 –

4

私の提案は、あなたのコードをリファクタリングすることです。この方法でdeferは、あなたが結果を処理前に接続を閉じます。

func dbQuery() error { 
    result, err := getResult() 
    if err != nil { 
     return err 
    } 
    // Processing the result takes a long time 

    return nil 
} 

func getResult() (*Rows, error) { 
    con := db.getConn() 
    defer con.close() // or con.close() 

    result, err := con.Query() 
    if err != nil { 
     return nil, err 
    } 

    return result, err 
} 
関連する問題