我试图让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]
这个坏孩子来了
答案 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
仍然需要访问实际实现Read
和Write
方法的类型。有关接口如何工作的更多详细信息,请参阅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
以便调用者知道它需要,并且能够在完成读取后关闭它。 Body
和File
都会实现ReadCloser
,因此唯一需要的更改是函数的返回签名。