<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Go1.2 on Roberto Selbach</title><link>https://rselbach.com/tags/go1.2/</link><description>Recent content in Go1.2 on Roberto Selbach</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Thu, 09 Jan 2014 15:35:00 +0000</lastBuildDate><atom:link href="https://rselbach.com/tags/go1.2/index.xml" rel="self" type="application/rss+xml"/><item><title>Coverage, TLS, and atomic swaps in Go 1.2</title><link>https://rselbach.com/coverage-tls-and-atomic-swaps-in-go-1-2/</link><pubDate>Thu, 09 Jan 2014 15:35:00 +0000</pubDate><guid>https://rselbach.com/coverage-tls-and-atomic-swaps-in-go-1-2/</guid><description>&lt;p&gt;Three Go 1.2 additions fixed three unrelated annoyances in one week. None is glamorous, which is usually a sign that I will use it.&lt;/p&gt;
&lt;p&gt;First, &lt;code&gt;go test&lt;/code&gt; now measures statement coverage directly:&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;cover&lt;/code&gt; tool is still distributed separately in &lt;code&gt;go.tools&lt;/code&gt;, so I installed it first:&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-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;$&lt;/span&gt; go get code&lt;span style="color:#f92672"&gt;.&lt;/span&gt;google&lt;span style="color:#f92672"&gt;.&lt;/span&gt;com&lt;span style="color:#f92672"&gt;/&lt;/span&gt;p&lt;span style="color:#f92672"&gt;/&lt;/span&gt;go&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tools&lt;span style="color:#f92672"&gt;/&lt;/span&gt;cmd&lt;span style="color:#f92672"&gt;/&lt;/span&gt;cover
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;$ go test -cover
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PASS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;coverage: 71.4% of statements
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ok example/parser 0.012s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For detail I use &lt;code&gt;go test -coverprofile=cover.out&lt;/code&gt;, followed by &lt;code&gt;go tool cover -func=cover.out&lt;/code&gt; or &lt;code&gt;go tool cover -html=cover.out&lt;/code&gt;. Coverage works by rewriting source with counters. It tells me which statements ran, not whether the assertions were intelligent. I can reach 100 percent while testing almost nothing; I have demonstrated this skill repeatedly.&lt;/p&gt;
&lt;p&gt;Second, &lt;code&gt;crypto/tls&lt;/code&gt; gained better control over protocol and cipher behavior, including TLS 1.2 support. For a client that must reject obsolete protocol versions I can set the minimum explicitly:&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;tr&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Transport&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;TLSClientConfig&lt;/span&gt;: &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;tls&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Config&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;MinVersion&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;tls&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;VersionTLS11&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;client&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Client&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Transport&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;tr&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I still let the standard library choose cipher suites unless interoperability forces my hand. A handwritten list ages, and a secure-looking list copied from a weblog ages especially well.&lt;/p&gt;
&lt;p&gt;Finally, &lt;code&gt;sync/atomic&lt;/code&gt; now has swap operations. I used one to replace a numeric generation and retrieve the previous value as a single atomic action:&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;old&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;atomic&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;SwapUint64&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;generation&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;generation %d -&amp;gt; %d&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;old&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The important phrase is &amp;ldquo;single atomic action.&amp;rdquo; Loading and then storing separately leaves a window in which another goroutine can intervene. A swap closes that window, but it does not magically protect related fields or establish a larger invariant. For that I still use a mutex.&lt;/p&gt;
&lt;p&gt;The default coverage mode counts whether statements execute. When tests exercise code concurrently, &lt;code&gt;-covermode=atomic&lt;/code&gt; makes counter updates safe, at additional cost. I do not compare benchmark timings from an instrumented coverage build with normal timings. The inserted counters are deliberately observable work.&lt;/p&gt;
&lt;p&gt;Atomics also require aligned, correctly typed storage and a design whose state really fits in one word. My generation counter does. A configuration containing a counter, pointer, and status does not become coherent because each field can be manipulated atomically. Readers could observe a combination that never represented one published configuration.&lt;/p&gt;
&lt;p&gt;I keep the atomic operation beside a comment describing that single-word invariant. Otherwise the next maintenance change tends to add a companion field and quietly invalidate the reasoning.&lt;/p&gt;
&lt;p&gt;These features share a useful property: they turn homemade approximations into explicit operations. I deleted a coverage script, avoided a custom TLS dialer, and replaced a dubious load/store pair. Upgrades are pleasant when the final diff is mostly subtraction.&lt;/p&gt;</description></item><item><title>What Go 1.2 changed under my goroutines</title><link>https://rselbach.com/what-go-1-2-changed-under-my-goroutines/</link><pubDate>Thu, 19 Dec 2013 18:10:00 +0000</pubDate><guid>https://rselbach.com/what-go-1-2-changed-under-my-goroutines/</guid><description>&lt;p&gt;One of my test programs had a rude goroutine: it performed a long loop containing function calls while another goroutine waited to print progress. With one processor, older Go releases could let the loop dominate longer than I liked.&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;spin&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;n&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:#a6e22e"&gt;total&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&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:#a6e22e"&gt;n&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;total&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;step&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;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;total&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:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;step&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;i&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 style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Go 1.2 introduces partial preemption when entering non-inlined functions. The scheduler can arrange for a goroutine to yield when it reaches one of these safe points. I built this experiment with &lt;code&gt;-gcflags=-l&lt;/code&gt; so the tiny &lt;code&gt;step&lt;/code&gt; call would remain a call. It does not make arbitrary Go code preemptible at every instruction. A tight loop with no calls can still be an unpleasant neighbor, and long cgo calls remain a different matter.&lt;/p&gt;
&lt;p&gt;That distinction matters. I first described the change to a colleague as &amp;ldquo;preemptive scheduling,&amp;rdquo; then wrote a no-call loop and disproved my own sentence. Progress became much fairer when the loop called &lt;code&gt;step&lt;/code&gt;, but not because the runtime had acquired a general-purpose interruptible stack map for every program counter.&lt;/p&gt;
&lt;p&gt;The other runtime change I can actually feel is stack size. New goroutine stacks in Go 1.2 start at 8 KiB rather than the smaller segments used before. That spends more virtual and physical memory up front, but avoids repeated stack splitting in modest call chains. In a crude test creating 100,000 blocked goroutines, memory is therefore not simply &amp;ldquo;100,000 times a tiny number.&amp;rdquo; Goroutines are cheap, not free.&lt;/p&gt;
&lt;p&gt;The segmented stacks still grow by linking stack segments. This is why a function prologue checks whether enough stack remains before proceeding. The check and occasional split are part of the cost hidden behind an ordinary call.&lt;/p&gt;
&lt;p&gt;I confirmed the scheduling effect with &lt;code&gt;GOMAXPROCS=1&lt;/code&gt;, because multiple operating-system threads otherwise conceal starvation by running both goroutines simultaneously. That is a useful test setting, not necessarily a production recommendation. With more processors, synchronization and cache traffic enter the result; the single-processor run isolates whether one runnable goroutine gets a chance to yield to another.&lt;/p&gt;
&lt;p&gt;Channel sends, receives, and system calls introduce other scheduling boundaries. My example intentionally removed those ordinary blocking points so the function-call behavior could be seen without a busy server around it.&lt;/p&gt;
&lt;p&gt;My practical rule remains boring: do not add &lt;code&gt;runtime.Gosched&lt;/code&gt; to every loop as seasoning. First determine whether the loop really starves useful work, then put natural blocking or chunking boundaries into the algorithm. Go 1.2 improves the worst behavior around calls, but it does not repeal scheduling.&lt;/p&gt;</description></item><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></channel></rss>