在 Go 中传递响应体 (response.Body) 的有效方法是什么?

如果我有一些代码,例如下面的示例,它从链接中获取图像然后将其保存到磁盘,那么传递图像数据的最佳方法是什么?


我想过使用ioutil.ReadAll(res.Body)将它转换为[]byte但传递它似乎很昂贵,尽管我无法从文档中判断它是否返回切片或数组。我也尝试返回一个指针res.Body,一个*io.ReadCloser类型,但我无法弄清楚如何正确地调用.Close()上的指示的方法来实现。


我知道将保存代码移到FetchImage函数中可能是解决此问题的最简单方法,但如果可能,我希望将这些部分分开。


type ImageData struct {

    Data      io.ReadCloser

    Name      string

}


func FetchImage(url string) (io.ReadCloser, error) {

    res, err := http.Get(url)

    if err != nil {

        return nil, err

    }

    return res.Body, nil

}


func Save(data *ImageData) error {

    defer data.Data.Close()

    file, err := os.Create(data.Name)

    defer file.Close()

    if err != nil {

        return err

    }

    _, err = io.Copy(file, data.Data)

    if err != nil {

        return err

    }

    return nil

}


func main() {

    body, err := fetcher.FetchImage("https://imgur.com/asdf.jpg")

    if err != nil {

        panic(err)

    }

    imageData := ImageData{body, "asdf.jpg"}

    saver := Saver{config.BaseDir, 1}

    err = saver.Save(&imageData)

    if err != nil {

        panic(err)

    }

}

此外,我对 Go 很陌生,所以如果这段代码中有任何看起来不好的地方,请告诉我。


杨魅力
浏览 185回答 2
2回答

子衿沉夜

使用ioutil.ReadAll。该函数返回一个字节片。切片可以有效地传递。切片是指向后备数组、长度和容量的指针。type ImageData struct {    Data      []byte    Name      string}func FetchImage(url string) ([]byte, error) {    res, err := http.Get(url)    if err != nil {        return nil, err    }    defer resp.Body.Close()    if res.StatusCode != 200 {        return nil, fmt.Errorf("%s: %d", url, res.StatusCode)    }    return ioutil.ReadAll(resp.Body)}func Save(data *ImageData) error {    file, err := os.Create(data.Name)    if err != nil {        return err    }    defer file.Close()    _, err := file.Write(data.Data)    return err}您也可以传递响应主体,但要小心。响应主体必须关闭才能释放底层连接。问题中的代码确实关闭了响应主体,但很难看到,因为响应主体传递到关闭它的函数。

Cats萌萌

在 Go 中,所有数组都有一个大小说明符,看起来像[8]byte. 切片不会有这个,看起来像[]byte。切片内部只存储一个指向数据的指针、切片的长度和切片的容量。在 64 位系统上这只是 24 个字节,因此您不必担心传递它。但是,我建议返回一个*ImageDatafromFetchImage因为它已经有像图像名称这样的元数据。至于为什么不能使用指向接口的指针,SO 上有一篇文章解释了原因。另外,在Save你defer file.Close()检查错误之前。您应该交换它,因为如果出现错误文件将为零,并且可能会出现段错误。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go