Resetting slice length and capacity

agolangf · · 651 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Does anyone know (or can guess) the reason for why there is no way to reset the length and capacity of a slice to that of its backing array?</p> <p><del>My own use case for such functionality would be a simple buffer pool, implemented as a channel. If the producer reads into the buffers from an io.Reader, it becomes natural to slice the buffer according to the number of bytes read, before sending it on a channel to a consumer. When the consumer is done with the buffer and sends it back on the buffer pool channel, there&#39;s currently no way of restoring the slice to the original length and capacity.</del> edit: My use case isn&#39;t valid, since the issue is easily solved using s[:cap(s)], as pointed out by lstokeworth. The question still stands though (e.g. return s[500:] -- original slice lost, caller cannot utilize all of the backing array).</p> <p>Yes, there are workarounds. But they are workarounds, and it would be nice to know why the limitation exists :)</p> <hr/>**评论:**<br/><br/>lstokeworth: <pre><p>Based on the description, it does not sound like the capacity is lost. Use the following expression to reset the length to the capacity: <code>a := [:cap(a)]</code></p></pre>aka_doode: <pre><p>Wow, I didn&#39;t think you could do that. I feel both stupid and grateful. Thank you! :)</p> <p>So I guess that limits potential use cases by quite a bit, but the question still stands.</p></pre>cbarrick: <pre><p>It&#39;s simple to reset the slice to be empty:</p> <pre><code>myslice = myslice[:0] </code></pre> <p>But I have a feeling that&#39;s not what you&#39;re looking for.</p> <p>If you &#34;reslice&#34; a slice, you are creating a new slice. The simplest way to &#34;reset&#34; to the original slice is to retain the original slice.</p> <pre><code>oldslice := &lt;-ch newslice := oldslice [a:b] // do stuff with newslice ch &lt;- oldslice[:0] </code></pre> <p><del>The capacity of a slice is always that of it&#39;s backing array there is no &#34;reset&#34; for capacity in that sense because it never changes.</del> edit: I forgot about the 3 argument slice expression.</p> <p>On the other hand, you can get a new slice by appending that allocates a new backing array if it needs more space than the original array.</p> <p>I&#39;m not sure I get exactly what you mean, but I hope this helps.</p></pre>lstokeworth: <pre><p>The capacity of a slice can be less than the size of the backing array when a full slice expression is used.</p></pre>cbarrick: <pre><p>Oh yeah. Totally forgot about that.</p></pre>aka_doode: <pre><p>I updated my question with a tiny example. I know that you can append to allocate a new array, but it would lead to reallocation of memory, and also increase memory usage (double the size).</p></pre>cbarrick: <pre><p>OK, I see now. My guess for the reason you can&#39;t do this is that it would require one more word in the slice header. A slice has three parts: a length, a capacity, and a pointer to the first element. To do what you&#39;re looking for, slices would also need a fourth pointer to the beginning of the array. I guess the language designers thought the 25% space savings per slice was worth the limitation. Considering the wide usage of slices, that was probably a good idea.</p> <p>Another problem I can see by allowing this is safety. Since you can&#39;t guarantee in general that the old slice is not still in use, if you copy data from the start of the new slice back to the beginning of the array, you would corrupt the data for users of the old slice. While there are still ways to corrupt data in one slice from the other in the current setup, all the ways I can think of involve corrupting the new slice from the old one, not the other way around.</p> <p>Since there is probably a way to structure all algorithms that would hit this issue in a way the would retain the old slice or otherwise avoid the problem, the space and safety benefits probably outweigh the convenience.</p></pre>aka_doode: <pre><p>All valid points. I&#39;d missed the &#34;security&#34; issue. Being able to do such a reset of a slice would likely make it possible to break all kinds of implementations... </p></pre>lstokeworth: <pre><blockquote> <p>The question still stands though (e.g. return s[500:] -- original slice lost, caller cannot utilize all of the backing array).</p> </blockquote> <p>The expression <code>s[500:]</code> does not affect the original slice <code>s</code>. The slice <code>s</code> still has access to the full backing array after the expression is evaluated.</p></pre>

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

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