Golang Type系统不一致(http包)

时间:2017-07-20 12:32:52

标签: go types interface

我正试图围绕GoLang类型系统,并且有一些事情让我感到困惑。

所以我一直在研究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 个答案:

答案 0 :(得分:2)

  

事实上,响应主体的类型为io.closer

不,不是。 Request.Body声明位于http://localhost/WebUI/Scripts/uicontrols/basic/fastsearch.js

Body io.ReadCloser

Request.Body字段的类型为Forked JSFiddle,它既是http.Request又是io.ReadCloser

由于它是io.Reader(动态值Request.Body实施io.Reader),您可以在需要io.Reader的位置使用/传递它,例如到io.Reader

由于它还实现了io.Closer,您也可以将其传递到需要io.Closer的地方,例如您的convert()功能。

但是在内部转换中,closer param具有静态类型io.Closer,您无法在需要closer的情况下使用in.Reader。存储在closer中的动态类型也可以(并且在您的情况下)也实现io.Reader,但不能保证这一点。就像在这个例子中一样:

type mycloser int

func (mycloser) Close() error { return nil }

func main() {
    var m io.Closer = mycloser(0)
    convert(m)
}

在上面的示例中,closer中的convert()将保留mycloser类型的值,该值实际上不会实现io.Reader

如果您的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
}