ioutil.ReadAll悲惨地失败

时间:2017-11-13 03:03:58

标签: go io null reader

我试图让io.Reader从这个天气回来,这是我给出的链接或路径。对于某些情况,我使用标记

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]
这个坏孩子来了

3 个答案:

答案 0 :(得分:5)

io.ReadWriter是一个接口,你需要的是io.ReadWriter的一个实例(通过io.Copy)写入并返回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的错误,这不是一个好主意。

答案 1 :(得分:3)

简单地将变量(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
}

答案 2 :(得分:0)

如果您只想从功能中退出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")
}

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