<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 "before" slice is the array up to, but excluding, the index. The "after" slice contains the index and the remainder of the array. I then used append to add my new value to the end of the "before" slice and appended the contents of the "after" 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'd really like to better understand slices. Can anyone help to explain what'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'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'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'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'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'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'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>
Understanding slices. A question on the use of append() to insert a value into a slice.
agolangf · · 392 次点击这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传