2017-07-20 3 views
-1

私はGoLangタイプのシステムの周りを頭で覆そうとしていますが、いくつか混乱しています。ゴランタイプのシステムの不一致(httpパッケージ)

私はこれを理解しようとするためにhttpライブラリに取り組んできましたが、私は意味をなさない以下を見てきました。

package main 

import (
    "net/http" 
    "fmt" 
    "io/ioutil" 
    "io" 
) 

func convert(closer io.Closer) ([]byte) { 
    body, _ := ioutil.ReadAll(closer); 
    return body 
} 

func main() { 

    client := &http.Client{} 
    req, _ := http.NewRequest("GET", "https://www.google.com", nil) 

    response, _ := client.Do(req); 

    body, _ := ioutil.ReadAll(response.Body) 

    fmt.Println(body); 
    fmt.Println(convert(response.Body)) 

} 

The Go Playground

これはコンバート機能は、それがレスポンスボディがタイプio.closerであり、ioutil.Readallがio.readerを取るという事実である必要はないという事実に関するものではありません、しかし、私はそれを一例で渡すことができますが、他の例ではそうではありません。魔法のように起こっているものがありますか?

私はReadメソッドを実装しているので、技術面では技術的に合格していますが、それは関数と本体の両方に当てはまるはずです。

洞察力はすばらしいと思います。

おかげ

+1

は、なぜあなたはそれが 'するかどう' io.Closer'を受け入れるために、 'convert'をしたいですかio.Reader'? – bereal

+2

'は、レスポンスボディがio.closer'型であるという事実です。... https://golang.org/src/net/http/response.goレスポンスのボディは' io.ReadCloser'型です。 – Gavin

+0

申し訳ありませんが、私はここで間違いを犯しました.HTML本体のデフォルトのタイプはio.ReadCloserです。これはメインパッケージhttps://golang.org/pkg/net/http/#Responseからのものです。 –

答えて

2

レスポンスボディいいえ、それはないです

io.closer型であるという事実です。 Request.Bodyの宣言はhttp.Requestである:

Body io.ReadCloser 

Request.Bodyフィールドは、それが両方io.Readerio.Closerあるタイプio.ReadCloserです。例えば

io.Readerが要求される場合、それはio.ReaderRequest.Body実装io.Readerの動的な値)であるため、使用できる/渡し、 ioutil.ReadAll()

io.Closerも実装されているため、convert()のようにio.Closerが必要な場所に渡すこともできます。

しかし、内部はcloser paramは、あなたがin.Readerが必要とされcloserを使用することはできません静的な型io.Closerを持って変換します。 closerに格納されているダイナミックタイプもio.Readerを実装している可能性があります(実際にはそうです)が、これは保証されていません。この例のように:convert()内部上記の例closer

真にio.Readerを実装していないタイプmycloser、の値を保持します。あなたのconvert()機能はio.Readerとしても、そのパラメータを処理することを意図した場合

、パラメータの型はio.ReadCloser次のようになります。

func convert(rc io.ReadCloser) ([]byte, error) { 
    body, err := ioutil.ReadAll(rc) 
    if err != nil { 
     return body, err 
    } 
    err = rc.Close() 
    return body, err 
}