我正在尝试获取io。读者从这种天气回来,这是我得到的链接或路径。对于某些上下文,我正在使用标志
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。复制(并返回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
仍然需要访问实际实现Read
和Write
方法的类型。有关接口工作原理的更多详细信息,请参阅此处。
至于上面的错误,您可以使用 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")
}
您可能希望返回一个io.ReadCloser
,以便调用方知道它需要,并且能够在完成读取后关闭它。Body
和 File
都实现了ReadCloser
因此唯一需要的更改是函数的返回签名。