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
仍然需要访问实际实现 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
}
如果您只想从函数返回 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
以便调用者知道它需要并且能够在完成读取后关闭它。 Body
和 File
都实现了 ReadCloser
,因此唯一需要更改的是函数的 return 签名。
我正试图从这种天气中恢复 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
仍然需要访问实际实现 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
}
如果您只想从函数返回 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
以便调用者知道它需要并且能够在完成读取后关闭它。 Body
和 File
都实现了 ReadCloser
,因此唯一需要更改的是函数的 return 签名。