Understanding slices. A question on the use of append() to insert a value into a slice.

agolangf · · 392 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I am attempting to insert an element into an array at a particular index. To do this I split the initial array in two, creating two slices. The &#34;before&#34; slice is the array up to, but excluding, the index. The &#34;after&#34; slice contains the index and the remainder of the array. I then used append to add my new value to the end of the &#34;before&#34; slice and appended the contents of the &#34;after&#34; slice to that.</p> <p>My first attempt failed but I have since fixed it after a lot of reading. I have reproduced my issue in the Go playground alongside the working version. I&#39;d really like to better understand slices. Can anyone help to explain what&#39;s going on? </p> <p><a href="https://play.golang.org/p/SicOVEclDf" rel="nofollow">https://play.golang.org/p/SicOVEclDf</a></p> <hr/>**评论:**<br/><br/>weberc2: <pre><p>Your second example doesn&#39;t work as you expect because <code>b</code> and <code>b[:i]</code> have the same backing array (they both have a capacity of 4 elements, starting at the same place in memory). The only difference is that <code>b[:i]</code> has a length of two elements. When you append to <code>b[:i]</code>, it grows the length by 1 and adds the new element in that position; however, this modifies the value stored in b[i], which is also the first element of b[i:]. So by <code>append(b[i:], 3)</code>, you are setting <code>b[i]=3</code>, which modifies the first element of <code>b[i:]</code> before you append it back onto the slice returned by <code>append(b[i:], 3)</code>.</p> <p>The first example works because it creates <em>a new temporary slice backed by a new array</em><sup>1</sup> via <code>[]int{3}</code>, and then copies <code>b[i:]</code> onto the end of it, so we have a new slice in memory that looks like <code>{3, b[i], b[i+1], etc}</code>. We then copy that onto <code>b[:i]</code>, overwriting the old contents with the new, correct contents.</p> <p>Here&#39;s a good article on the mechanics of append: <a href="https://blog.golang.org/slices" rel="nofollow">https://blog.golang.org/slices</a></p> <p><sup>1:</sup> The extra allocation can be expensive in a tight loop; the trick to avoid this allocation is:</p> <pre><code>// extend the *length* of the array by one; this will // allocate a larger backing array, but only if necessary s = append(s, 0) // shift the right-hand-side over one element, creating a // 1-element-wide gap between the left/right sides of the // insert copy(s[i+1:], s[i:]) // write the inserted element into the gap s[i] = x </code></pre></pre>goomba_gibbon: <pre><p>Perfect. Thank you so much for the detailed answer! This makes a lot of sense. I understood that slices were backed by an array but couldn&#39;t figure it out.</p> <p>I think the piece I had missed was that <code>append(b[i:], 3)</code> was actually modifying the underlying array of <code>b</code>, not allocating a new one. I think that makes sense.</p></pre>weberc2: <pre><p>No worries. I&#39;m happy to help. This tripped me up in exactly the same way. The good news is that this should be the last conceptual speed-bump you hit--your concept of slices should now be more or less complete. :)</p></pre>goomba_gibbon: <pre><p>Well it&#39;s on reddit now for posterity. Thanks again!</p></pre>plaverde: <pre><p>Here is a cleaner solution: <a href="https://play.golang.org/p/FdrGL1JHV8" rel="nofollow">https://play.golang.org/p/FdrGL1JHV8</a></p></pre>AmduX: <pre><p>Have a look at: <a href="https://github.com/golang/go/wiki/SliceTricks" rel="nofollow">https://github.com/golang/go/wiki/SliceTricks</a></p> <p>Awesome tips and tricks, helped me a lot.</p></pre>goomba_gibbon: <pre><p>Thanks. I had found this already. The tricks are nice but i want to understand what&#39;s going on.</p></pre>msgtonaveen: <pre><p>I have wrote a detail tutorial on arrays and slices <a href="https://golangbot.com/arrays-and-slices/" rel="nofollow">https://golangbot.com/arrays-and-slices/</a>. It will help you understand how arrays and slices work.</p></pre>goomba_gibbon: <pre><p>It was a great read. Thanks!</p></pre>

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

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