What's an efficient way to pass a response body (response.Body) in Go?
如果我有一些代码(例如下面的示例),该代码从链接中获取图像,然后将其保存到磁盘,那么传递图像数据的最佳方法是什么?
我曾考虑过使用
我知道将保存代码移到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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还是很陌生,所以如果这段代码中有什么看起来很糟糕,请告诉我。
在Go中,所有数组都有一个大小说明符,看起来像
但是,我建议从
至于为什么不能使用指向接口的指针,SO上有一篇文章解释了为什么。
另外,在
使用ioutil.ReadAll。该函数返回一个字节片。
切片有效地传递。切片是指向后备数组,长度和容量的指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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 } |
您也可以绕过响应正文,但要小心。必须关闭响应主体以释放基础连接。问题中的代码确实关闭了响应主体,但是很难看到,因为响应主体是沿着关闭它的函数传递的。