【问题标题】:ioutil.ReadAll fails miserablyioutil.ReadAll 惨遭失败
【发布时间】:2018-04-25 16:11:00
【问题描述】:

我正在尝试从这种天气中获取一个 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]

这个坏男孩来了

【问题讨论】:

    标签: go io null reader


    【解决方案1】:

    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 的错误,这不是一个好主意。

    【讨论】:

      【解决方案2】:

      仅将变量 (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
      }
      

      【讨论】:

        【解决方案3】:

        如果您只想从函数返回 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,因此唯一需要更改的是函数的返回签名。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-01-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-11
          • 2015-03-03
          • 1970-01-01
          相关资源
          最近更新 更多