読者です 読者をやめる 読者になる 読者になる

たぶんみんな間違えてる golang の HTTP Respose Body の閉じ方

元ネタはこちらのブログ.

50 Shades of Go: Traps, Gotchas, and Common Mistakes for New Golang Devs

あまりにも衝撃的でした.HTTP Response の Body を閉じるとき,たぶん,みんなこう書いてると思うんだけど,

誤)エラーがないかチェックしてから閉じるようにしておく

resp, err := http.Get("http://golang.org")
    if err != nil {
        return err
    }
    defer resp.Body.Close()

エラーがあっても,Response が nil じゃないときがあるらしい.なので,正しい閉じ方はこう.

正)Response が nil じゃなかったら閉じるようにしてからエラーをチェックする

resp, err := http.Get("https://api.ipify.org?format=json")
    if resp != nil {
        defer resp.Body.Close()    // ← ここで nil じゃないときは閉じるようにしておく
    }
    if err != nil {
        return err
    }

http.Get(...) の処理を追っかけて golang のソース見てみたら,こんなコードがありました. http://golang.org/src/net/http/client.go?s=9711:9771#L400

     if redirectFailed {
            // Special case for Go 1 compatibility: return both the response
            // and an error if the CheckRedirect function failed.
            // See http://golang.org/issue/3795
            return resp, urlErr
        }

特殊なケースとして Go 1 互換にするためにリダイレクトの時は(?)レスポンスとエラーを両方返すようにしています.これがあるせいで,エラーがあってもレスポンスがあるときがあるんですね...

みんな正しく書いてたでしょうか?間違ってたのは僕だけ?

追記:2015-06-05

つづき → 結局 golang の HTTP Response Body はどう閉じるのが正しいのか? - 押してダメならふて寝しろ