为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
杨魅力 2021-12-27 14:59:25
如果我有一些代码,例如下面的示例,它从链接中获取图像然后将其保存到磁盘,那么传递图像数据的最佳方法是什么?我想过使用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 很陌生,所以如果这段代码中有任何看起来不好的地方,请告诉我。
查看完整描述

2 回答

?
子衿沉夜

TA贡献1828条经验 获得超3个赞

使用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

}

您也可以传递响应主体,但要小心。响应主体必须关闭才能释放底层连接。问题中的代码确实关闭了响应主体,但很难看到,因为响应主体传递到关闭它的函数。


查看完整回答
反对 回复 2021-12-27
?
Cats萌萌

TA贡献1805条经验 获得超9个赞

在 Go 中,所有数组都有一个大小说明符,看起来像[8]byte. 切片不会有这个,看起来像[]byte。切片内部只存储一个指向数据的指针、切片的长度和切片的容量。在 64 位系统上这只是 24 个字节,因此您不必担心传递它。

但是,我建议返回一个*ImageDatafromFetchImage因为它已经有像图像名称这样的元数据。

至于为什么不能使用指向接口的指针,SO 上有一篇文章解释了原因。

另外,在Savedefer file.Close()检查错误之前。您应该交换它,因为如果出现错误文件将为零,并且可能会出现段错误。


查看完整回答
反对 回复 2021-12-27
  • 2 回答
  • 0 关注
  • 184 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信