<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Slices on Roberto Selbach</title><link>https://rselbach.com/tags/slices/</link><description>Recent content in Slices on Roberto Selbach</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Thu, 05 Dec 2013 14:45:00 +0000</lastBuildDate><atom:link href="https://rselbach.com/tags/slices/index.xml" rel="self" type="application/rss+xml"/><item><title>Three-index slices and capacity</title><link>https://rselbach.com/three-index-slices-and-capacity/</link><pubDate>Thu, 05 Dec 2013 14:45:00 +0000</pubDate><guid>https://rselbach.com/three-index-slices-and-capacity/</guid><description>&lt;p&gt;I upgraded a small service to Go 1.2 and immediately found a use for the new full slice expression. That sounds implausibly efficient for an upgrade, so naturally it followed a bug.&lt;/p&gt;
&lt;p&gt;I had a helper that accepted a prefix of a work buffer and appended a marker:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mark&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;) []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; append(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;!&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;buf&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []byte(&lt;span style="color:#e6db74"&gt;&amp;#34;abcdef&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;prefix&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;buf&lt;/span&gt;[:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;marked&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mark&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;prefix&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s %s\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;marked&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;buf&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I expected a separate &lt;code&gt;abc!&lt;/code&gt;. I got:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;abc! abc!ef
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The ordinary two-index slice preserves the unused capacity of the backing array. &lt;code&gt;prefix&lt;/code&gt; had length 3 but capacity 6, so &lt;code&gt;append&lt;/code&gt; reused the array and replaced &lt;code&gt;d&lt;/code&gt;. The helper&amp;rsquo;s signature did not advertise permission to alter bytes beyond the visible slice, but capacity quietly granted exactly that permission.&lt;/p&gt;
&lt;p&gt;Go 1.2 adds a third index:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;prefix&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;buf&lt;/span&gt;[:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For &lt;code&gt;a[low:high:max]&lt;/code&gt;, the length is &lt;code&gt;high-low&lt;/code&gt; and the capacity is &lt;code&gt;max-low&lt;/code&gt;. Now the output is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;abc! abcdef
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Because &lt;code&gt;len(prefix) == cap(prefix)&lt;/code&gt;, append must allocate another backing array. This is not an immutable slice. The helper can still change &lt;code&gt;prefix[0]&lt;/code&gt;, and anyone sharing the original array will see that change. The third index controls append&amp;rsquo;s room, nothing more.&lt;/p&gt;
&lt;p&gt;It is also useful when dividing one large buffer among independent workers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;left&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;buf&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;right&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;buf&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Appending to &lt;code&gt;left&lt;/code&gt; can no longer wander into &lt;code&gt;right&lt;/code&gt;. Before 1.2 I used &lt;code&gt;append([]byte(nil), buf[:3]...)&lt;/code&gt;, which copies eagerly and obscures why. The full slice expression is both cheaper and more precise when all I need is a capacity fence.&lt;/p&gt;
&lt;p&gt;The indices must satisfy &lt;code&gt;0 &amp;lt;= low &amp;lt;= high &amp;lt;= max &amp;lt;= cap(a)&lt;/code&gt;. The upper capacity bound is checked at run time just like an ordinary slice bound. I find it useful to print both dimensions when debugging ownership:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;len=%d cap=%d\n&amp;#34;&lt;/span&gt;, len(&lt;span style="color:#a6e22e"&gt;prefix&lt;/span&gt;), cap(&lt;span style="color:#a6e22e"&gt;prefix&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Reslicing later cannot recover the fenced-off capacity. The slice header handed to the helper records only a pointer, length, and reduced capacity; it carries no secret reference to my original wider view.&lt;/p&gt;
&lt;p&gt;For an array rather than a slice, the omitted low index still defaults to zero. I write all three values at boundaries anyway; explicit fences are easier to review than clever shorthand.&lt;/p&gt;
&lt;p&gt;My caveat is that I would not scatter three-index slices everywhere. Most slices should share capacity normally. I use the extra index at ownership boundaries, where an append by a callee would otherwise mutate storage it does not conceptually own.&lt;/p&gt;</description></item><item><title>The Slice Is Not the Array</title><link>https://rselbach.com/the-slice-is-not-the-array/</link><pubDate>Thu, 04 Nov 2010 21:04:00 +0000</pubDate><guid>https://rselbach.com/the-slice-is-not-the-array/</guid><description>&lt;p&gt;Coming from C, I first read a Go slice as a pointer with nicer indexing. That model works until &lt;code&gt;append&lt;/code&gt; allocates a new backing array or a tiny subslice keeps a large allocation alive. The missing piece is that a slice is a small descriptor, not the array itself.&lt;/p&gt;
&lt;p&gt;Conceptually, the descriptor contains three items:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;+---------+--------+----------+
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| pointer | length | capacity |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;+---------+--------+----------+
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;+----+----+----+----+----+
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| 10 | 20 | 30 | 40 | 50 |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;+----+----+----+----+----+
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The pointer identifies an element in a backing array. Length controls the elements currently accessible through indexing. Capacity describes how far the slice may grow from that starting point before another array is needed. This is a conceptual layout, not a promise that user code should depend on runtime internals.&lt;/p&gt;
&lt;p&gt;Given an array and a slice:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(len(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;), cap(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;my snapshot prints:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2 4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The slice sees &lt;code&gt;20&lt;/code&gt; and &lt;code&gt;30&lt;/code&gt;, and it has capacity through the end of &lt;code&gt;a&lt;/code&gt;. Assigning &lt;code&gt;s[0] = 99&lt;/code&gt; changes &lt;code&gt;a[1]&lt;/code&gt; because both views refer to the same storage. Passing &lt;code&gt;s&lt;/code&gt; to a function copies the descriptor, but both descriptors still point at that storage.&lt;/p&gt;
&lt;p&gt;This explains a function that appears not to resize its caller:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;grow&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; = append(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The local descriptor changes. The caller&amp;rsquo;s descriptor does not. If the append fits within capacity, the backing array may contain the new element, but the caller&amp;rsquo;s length still excludes it. If it does not fit, append obtains another backing array and the local slice points there. The useful pattern is to return the result:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;grow&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) []&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; append(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;grow&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The same mechanism makes append performance less mysterious. Growing one element at a time does not normally allocate an array on every call. Capacity grows in larger steps and existing elements are copied when storage changes. The exact growth policy belongs to this experimental runtime and should not become an application assumption.&lt;/p&gt;
&lt;p&gt;I verified allocations indirectly by timing construction with and without an initial capacity:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make([]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;100000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &amp;lt; &lt;span style="color:#ae81ff"&gt;100000&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; = append(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When the final size is known, reserving capacity avoids repeated growth and copying. When it is not known, append&amp;rsquo;s policy is generally better than inventing my own allocation scheme. Capacity is a performance hint with semantic consequences, not a target to maximize.&lt;/p&gt;
&lt;p&gt;Subslice lifetime is the less obvious consequence. I wrote a reader that loaded a large file, found one short token, and returned a slice containing that token. The token was only a few bytes, but its descriptor still pointed into the large backing array. As long as the small slice remained reachable, the collector could not reclaim the array.&lt;/p&gt;
&lt;p&gt;The fix was to copy the useful bytes into a new, correctly sized slice:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;token&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make([]&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;end&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;copy(&lt;span style="color:#a6e22e"&gt;token&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;:&lt;span style="color:#a6e22e"&gt;end&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;token&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Copying sounds wasteful until the alternative is retaining several megabytes for a twelve-byte identifier. Profiling the whole process settled that argument quickly.&lt;/p&gt;
&lt;p&gt;Overlapping slices deserve similar care. &lt;code&gt;copy&lt;/code&gt; is the operation intended for moving slice contents, including overlap supported by the implementation. Hand-written forward loops can overwrite input before reading it. This is one of those cases where code that looks closer to C is merely closer to a C bug.&lt;/p&gt;
&lt;p&gt;Slices also make zero values useful. A nil slice has length and capacity zero, can be ranged over, and can be appended to. For many producers there is no need to allocate an empty slice eagerly. An empty non-nil slice may still matter at an encoding boundary, but inside the program I prefer the simpler zero value unless behavior says otherwise.&lt;/p&gt;
&lt;p&gt;Arrays remain values with their length in the type. Assigning an array copies its elements, and &lt;code&gt;[4]int&lt;/code&gt; differs from &lt;code&gt;[5]int&lt;/code&gt;. Slices provide the flexible view normally wanted by functions. Remembering that distinction prevents a great deal of accidental copying and aliasing.&lt;/p&gt;
&lt;p&gt;All of this describes the November 2010 toolchain I am using. Syntax, built-ins, and growth details may change before a stable release. The useful mental model is simpler: a slice is a copied descriptor over shared storage. Ask which descriptor changes, which array it references, and who keeps that array alive. That usually finds the surprise.&lt;/p&gt;</description></item></channel></rss>