emahiro/b.log

Drastically Repeat Yourself !!!!

僕の考える net/http の定数の使いどころ

Overview

Go の net/httpパッケージ には HTTP に関連する定数が予め定義されており、HTTP クライアントを実装するときなどに自前で定義したり、GET200 といった定数を実装しなくてもいいように、標準の net/http がデザインされています。
こういう実装側で毎回用意してしまいそうな定数すら、Go は標準ライブラリで用意してくれているので、基本的にはこの定数を実装でも使っていきたいところですが、実際どういう時に使うといいのか、逆に使わないべきなのか、という点について自分なりの考えをまとめてみました。

TL;DR

  • HTTP に関係する定数は自前で定義せずに net/http で予め定義されてる定数を使おう。
  • レスポンスコードを比較するケースでは、HTTP レスポンスコードの定数よりも数字の方が可読性は高いかもね。

net/http の定数

定数一覧は net/http の Godoc を見ればわかります。

検討 - net/http の定数の使いどころ

使うべきケース

1. HTTP リクエストを作成するとき

以下のように使います。

req, err := http.NewRequest(http.MethodGet, "https://emahiro.dev", nil)

これは

req, err := http.NewRequest("GET", "https://emahiro.dev", nil)

と書いても同じですが、毎回 "GET" 書いてるとそのうち定数にしたくなる時がくると思います。
その時に定数にするくらいなら最初から net/http で定義されてる定数を使っておきましょう。

2. 正常系をチェックするとき

以下のような正常系チェックの時は、http.StatusOK を書いた方が正常系と異常系のチェックを示すという点で、直感的にはわかりやすいかと思います。

resp, err := client.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
   // 異常系のハンドリング
}

※ 一方で異常系で 400系, 500系の場合分けを行うケースでは、数字の方が比較を直感的に理解しやすいと考えたので後述の「使うべきでないケース」に追記しました。

3. HTTP のステータスコードを返すとき

これは言わずもがなかと思います。ステータスコードを指定して返すときは net/http に定数を使いましょう。

func(w http.ResponseWriter, r *http.Request){
    w.WriteHeader(http.StatusInternalServerError)
    w.Write([]byte(`hello`))
}

どのステータスコードを返すのか直感的にわかります。

4. HTTPのステータスメッセージを返すとき

これはすべき、というレベルではないのですが、HTTP のステータスコードに紐づくメッセージを返すときに Go の net/http package には StatusText というメソッドが用意されており、ステータスコードを渡すとそれにひもづくステータスコードのメッセージを返してくれるので便利です。

http.StatusText(http.StausOK) 
// Output: OK

http.StatusText(http.StatusInternalServerError) 
// Outout: Internal Server Error 

使うべきでないケース

1. レスポンスコードを比較して正常/異常系をハンドリングするとき

以下のようなケースでは数字のまま比較した方が直感的かもしれません。

resp, err := client.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

if 400 <= resp.StatusCode && resp.StatusCode < 500 {
   // 400系のハンドリング
}

if 500 <= resp.StatusCode {
   // 500系のハンドリング
}

以下のように書いても同じですが、

resp, err := client.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

if http.StatusBadRequest <= resp.StatusCode && resp.StatusCode < http.StatusIntenalServerError {
   // 400系のハンドリング
}

if http.StatusInternalServerError <= resp.StatusCode {
   // 500系のハンドリング
}

http.StatusBadRequest = 400 だなと頭の中で一度変換が入る、かつこのケースでは範囲で比較をしたいのであって、ステータスコード単体のチェックを行いたいわけではないので、数字のまま比較した方がより直感的な表現になると考えています。

まとめ

Go のコードを書いてて net/http 内に HTTP 関連のステータスがあらかじめ定義されてることを知った時はとても便利で多用しがちでしたが、数字の比較など逆に直感的でないケースもあるので、どういう指針でコードを書いてるのかを備忘録として記載しました。