Question: Does json.Decode / json.NewDecoder close the http stream or do you still need a defer body.close()?

agolangf · · 753 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hi guys.</p> <p>So, I&#39;ve got this code:</p> <pre><code> ... resp, _ := http.Get(server + &#34;/api/1/list&#34;) agents := []Agent{} decoder := json.NewDecoder(resp.Body) err := decoder.Decode(&amp;agents) if err != nil { fmt.Fprintf(w, &#34;error occured:&#34;+err.Error()) return } ... </code></pre> <p>Pretty straight forward. Reads a stream of json data from the response body. In the early days of Go before Decoder, I was doing a lot of magic, and checking a lot of errors and doing a defer body.close(). Now this came along and I seem to remember not need a body close anymore, since it reads the stream to finish ( I think. ). As I&#39;m now going through the code for Decoder, I&#39;m not sure anymore. :) </p> <p>So... Can somebody please say a yay or nay? </p> <p>Thanks!</p> <hr/>**评论:**<br/><br/>fortytw2: <pre><p><code>json.NewDecoder</code> takes an <code>io.Reader</code>, meaning it can&#39;t magically close it on it&#39;s own. You still need to close the response body yourself, but there might be some additional kung-fu to ensure the body is drained before closing so the connection gets re-used correctly (let me see if I can find these links)</p></pre>earthboundkid: <pre><p>You can ask for one interface then use reflection to promote it to another. No one does this for ReadCloser because of separation of concerns, but io.Copy does internally check for ReadFrom and WriteTo and use those methods if possible. </p> <p>See <a href="https://golang.org/src/io/io.go#L369">https://golang.org/src/io/io.go#L369</a></p></pre>skarlso: <pre><p>Wow, that&#39;s an interesting one. Thanks!</p></pre>skarlso: <pre><p>Cool! Thanks forty. :))</p></pre>schumacherfm: <pre><p>I think you mean this code snippet ... I hope I remember correctly:</p> <pre><code>defer resp.Body.Close() defer func() { // read until the response is complete if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil { panic(err) // find another better way to avoid this } }() </code></pre></pre>tv64738: <pre><p>The io.Copy is not needed, just the close.</p></pre>schumacherfm: <pre><p>Thanks! Good know!</p></pre>stone_henge: <pre><p>Have a look at the different I/O interfaces. They will give you a hint as to how functions will use them.</p> <p><a href="https://golang.org/pkg/io/#Reader" rel="nofollow">io.Reader</a> only specifies a Read method, so that is the only operation a function expecting that interface will be able to use. (without using type switches and complete knowledge of what types you might throw at it).</p> <p>If it expected an <a href="https://golang.org/pkg/io/#ReadCloser" rel="nofollow">io.ReadCloser</a> it would have been able to call Close, too. I&#39;ve found that when something does, it&#39;s usually specified in the documentation.</p></pre>skarlso: <pre><p>Ahh that makes sense. Thanks. And kudos for the future, for me to what to take a look at when next time searching for something like this!! Coolness. Thanks again! :)</p> <p>Just to be clear... This is the interface for the Decoder =&gt;</p> <pre><code>// A Decoder reads and decodes JSON objects from an input stream. type Decoder struct { r io.Reader buf []byte d decodeState scanp int // start of unread data in buf scan scanner err error tokenState int tokenStack []int } </code></pre> <p>Since this guy does not define a closer, it won&#39;t be able to close the reader r. Right?</p></pre>stone_henge: <pre><p>I think it&#39;s a better reference to look at the constructor (&#34;NewDecoder&#34;), where the only input is an <code>io.Reader</code> but yeah, you can also tell from here that it only stores an <code>io.Reader</code>, which is its reference to the Body stream once you&#39;ve created the decoder with NewDecoder. But yes, you are correct.</p></pre>skarlso: <pre><p>Cool, gotcha. Thanks a bunch!! :)</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

753 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传