ioutil.ReadAll惨败

ioutil.ReadAll fails miserably

我正试图从这种天气中恢复 io.Reader 它是 link 或我得到的路径。在某些情况下,我使用 flags

func getString(link, path string) (io.Reader, error) {

    var dick io.ReadWriter

    if link != "" {
        resp, err := http.Get(link)
        if err != nil {
            return nil, err
        }

        io.Copy(dick, resp.Body)
    }

    if path != "" {
        file, err := os.Open(path)
        if err != nil {
            return nil, err
        }

        io.Copy(dick, file)
    }

    return dick, nil

}

繁荣

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x46e949]

这个坏小子来了

io.ReadWriter 是一个接口,你需要的是 io.ReadWriter 的实例写入(通过 io.Copy)和 return io.Reader 接口关闭那个。

想到的一种类型是 bytes.Buffer。你的代码看起来像这样

func getString(link, path string) (io.Reader, error) {

    dick := bytes.NewBuffer(nil)

    if link != "" {
        resp, err := http.Get(link)
        if err != nil {
            return nil, err
        }

        io.Copy(dick, resp.Body)
    }

    if path != "" {
        file, err := os.Open(path)
        if err != nil {
            return nil, err
        }

        io.Copy(dick, file)
    }

    return dick, nil

}

您也接受了 io.Copy 的错误,这不是一个好主意。

简单地将变量 (dick) 声明为接口类型 (io.ReadWriter) 不会创建将处理接口方法实现的具体类型。

dick 仍然需要访问实际实现 ReadWrite 方法的类型。有关接口如何工作的更多详细信息,请参阅 here

至于上面的错误,可以用bytes.Buffer。此类型已满足 io.ReadWriter 接口。

func getString(link, path string) (io.Reader, error) {
    var dick bytes.Buffer // bytes.Buffer is an io.ReadWriter.
    if link != "" {
        resp, err := http.Get(link)
        // ...
        io.Copy(dick, resp.Body)
    }
    // ...
    return dick, nil
}

如果您只想从函数返回 Reader,它比其他答案简单得多。 io.Copy、缓冲区等完全没有必要:

func getString(link, path string) (io.Reader, error) {
    if link != "" {
        resp, err := http.Get(link)
        if err != nil {
            return nil, err
        }
        return resp.Body, err // http.Response.Body implements io.Reader
    }

    if path != "" {
        return os.Open(path) // os.File implements io.Reader
    }

    return nil, errors.New("No path or link given")
}

您可能想要 return 一个 io.ReadCloser 以便调用者知道它需要并且能够在完成读取后关闭它。 BodyFile 都实现了 ReadCloser,因此唯一需要更改的是函数的 return 签名。