私は GAE 用のアプリを作成して Go を学習しています。これはハンドラー関数の署名です。
func handle(w http.ResponseWriter, r *http.Request) {}
私はここではポインターの初心者ですが、なぜRequest
オブジェクトはポインターなのResponseWriter
ですか? このようにする必要はありますか、それとも、ある種の高度なポインターベースのコードを可能にするためだけですか?
得られるのw
は、エクスポートされていない型へのポインターですが、インターフェイスとhttp.response
同様に、それは表示さResponseWriter
れません。
server.goから:
type ResponseWriter interface {
...
}
一方、r
は具体的な構造体へのポインターであるため、参照を明示的に渡す必要があります。
request.goから:
type Request struct {
...
}
はhttp.ResponseWriter
インターフェースであり、このインターフェースを実装する既存のタイプはポインターです。つまり、このインターフェイスはすでにポインタによって「バックアップ」されているため、このインターフェイスへのポインタを使用する必要はありません。この概念は、ここでgo開発者の1人によって少し説明されています。http.ResponseWriterを実装するタイプはポインターである必要はありませんが、少なくともgohttpサーバー内では実用的ではありません。
http.Request
はインターフェースではなく、単なる構造体です。この構造体を変更してWebサーバーにそれらの変更を認識させたいので、ポインターである必要があります。構造体の値だけの場合は、コードを呼び出すWebサーバーが認識できないコピーを変更するだけです。
これが Request へのポインターである理由は単純です。ハンドラーによる Request への変更はサーバーに表示される必要があるため、値ではなく参照によって渡すだけです。
net/http ライブラリ コードを掘り下げると、ResponseWriter がエクスポートされていない構造体応答へのインターフェイスであり、値ではなく参照によって構造体を渡している (応答へのポインターを渡している) ことがわかります。 . ResponseWriter は、ハンドラーが HTTP 応答を作成するために使用するインターフェースです。ResponseWriter をバックアップする実際の構造体は、エクスポートされていない構造体 http.response です。エクスポートされていないため、直接使用することはできません。ResponseWriter インターフェイスを介してのみ使用できます。
つまり、両方のパラメーターが参照によって渡されます。メソッドのシグネチャが、構造体へのポインターへのインターフェイスである ResponseWriter を受け取るだけなので、値で渡されたかのように見えます。
Request
オブジェクトがポインタとして渡される主な理由はフィールドだと思いBody
ます。特定の HTTP リクエストについて、ボディは 1 回しか読み取れません。オブジェクトが複製された場合はRequest
、ポインターとして渡されなかった場合と同様に、本体から読み取られた量に関する異なる情報を持つ 2 つのオブジェクトが作成されます。