Congratulations!

[Valid Atom 1.0] This is a valid Atom 1.0 feed.

Recommendations

This feed is valid, but interoperability with the widest range of feed readers could be improved by implementing the following recommendations.

Source: http://blog.golang.org/feed.atom

  1. <feed xmlns="http://www.w3.org/2005/Atom"><title>The Go Blog</title><id>tag:blog.golang.org,2013:blog.golang.org</id><link rel="self" href="https://go.dev/blog/feed.atom"></link><updated>2024-05-02T00:00:00+00:00</updated><entry><title>Secure Randomness in Go 1.22</title><id>tag:blog.golang.org,2013:blog.golang.org/chacha8rand</id><link rel="alternate" href="https://go.dev/blog/chacha8rand"></link><published>2024-05-02T00:00:00+00:00</published><updated>2024-05-02T00:00:00+00:00</updated><author><name></name></author><summary type="html">ChaCha8Rand is a new cryptographically secure pseudorandom number generator used in Go 1.22.</summary><content type="html">&#xA;&lt;div id=&#34;blog&#34;&gt;&lt;div id=&#34;content&#34;&gt;&#xA;  &lt;div id=&#34;content&#34;&gt;&#xA;&#xA;    &lt;div class=&#34;Article&#34; data-slug=&#34;/blog/chacha8rand&#34;&gt;&#xA;    &#xA;    &lt;h1 class=&#34;small&#34;&gt;&lt;a href=&#34;/blog/&#34;&gt;The Go Blog&lt;/a&gt;&lt;/h1&gt;&#xA;    &#xA;&#xA;    &lt;h1&gt;Secure Randomness in Go 1.22&lt;/h1&gt;&#xA;      &#xA;      &lt;p class=&#34;author&#34;&gt;&#xA;      Russ Cox and Filippo Valsorda&lt;br&gt;&#xA;      2 May 2024&#xA;      &lt;/p&gt;&#xA;      &#xA;      &lt;p&gt;Computers aren&amp;rsquo;t random.&#xA;On the contrary, hardware designers work very hard to make sure computers run every program the same way every time.&#xA;So when a program does need random numbers, that requires extra effort.&#xA;Traditionally, computer scientists and programming languages&#xA;have distinguished between two different kinds of random numbers:&#xA;statistical and cryptographic randomness.&#xA;In Go, those are provided by &lt;a href=&#34;/pkg/math/rand/&#34;&gt;&lt;code&gt;math/rand&lt;/code&gt;&lt;/a&gt;&#xA;and &lt;a href=&#34;/pkg/crypto/rand&#34;&gt;&lt;code&gt;crypto/rand&lt;/code&gt;&lt;/a&gt;, respectively.&#xA;This post is about how Go 1.22 brings the two closer together,&#xA;by using a cryptographic random number source in &lt;code&gt;math/rand&lt;/code&gt;&#xA;(as well as &lt;code&gt;math/rand/v2&lt;/code&gt;, as mentioned in our &lt;a href=&#34;/blog/randv2&#34;&gt;previous post&lt;/a&gt;).&#xA;The result is better randomness and far less damage when&#xA;developers accidentally use &lt;code&gt;math/rand&lt;/code&gt; instead of &lt;code&gt;crypto/rand&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Before we can explain what Go 1.22 did, let&amp;rsquo;s take a closer look&#xA;at statistical randomness compared to cryptographic randomness.&lt;/p&gt;&#xA;&lt;h2 id=&#34;statistical-randomness&#34;&gt;Statistical Randomness&lt;/h2&gt;&#xA;&lt;p&gt;Random numbers that pass basic statistical tests&#xA;are usually appropriate for use cases like simulations, sampling,&#xA;numerical analysis, non-cryptographic randomized algorithms,&#xA;&lt;a href=&#34;/doc/security/fuzz/&#34;&gt;random testing&lt;/a&gt;,&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;shuffling inputs&lt;/a&gt;,&#xA;and&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Exponential_backoff#Collision_avoidance&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;random exponential backoff&lt;/a&gt;.&#xA;Very basic, easy to compute mathematical formulas turn out to work&#xA;well enough for these use cases.&#xA;Because the methods are so simple, however, an observer who&#xA;knows what algorithm is being used can typically predict the rest&#xA;of the sequence after seeing enough values.&lt;/p&gt;&#xA;&lt;p&gt;Essentially all programming environments provide a mechanism for generating&#xA;statistical random numbers&#xA;that traces back through C to&#xA;Research Unix Third Edition (V3), which added a pair of functions: &lt;code&gt;srand&lt;/code&gt; and &lt;code&gt;rand&lt;/code&gt;.&#xA;The manual page included&#xA;a note that read:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;em&gt;WARNING   The author of this routine has been writing&#xA;random-number generators for many years and has never been&#xA;known to write one that worked.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This note was partly a joke but also an acknowledgement that such&#xA;generators are &lt;a href=&#34;https://www.tuhs.org/pipermail/tuhs/2024-March/029587.html&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;inherently not random&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The source code of the generator makes clear how trivial it is.&#xA;Translated from PDP-11 assembly to modern C, it was:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;uint16 ranx;&#xA;&#xA;void&#xA;srand(uint16 seed)&#xA;{&#xA;    ranx = seed;&#xA;}&#xA;&#xA;int16&#xA;rand(void)&#xA;{&#xA;    ranx = 13077*ranx + 6925;&#xA;    return ranx &amp;amp; ~0x8000;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Calling &lt;code&gt;srand&lt;/code&gt; seeds the generator with a single integer seed,&#xA;and &lt;code&gt;rand&lt;/code&gt; returns the next number from the generator.&#xA;The AND in the return statement clears the sign bit to make sure the result is positive.&lt;/p&gt;&#xA;&lt;p&gt;This function is an instance of the general class of&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Linear_congruential_generator&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;linear congruential generators (LCGs)&lt;/a&gt;,&#xA;which Knuth analyzes in &lt;em&gt;The Art of Computer Programming&lt;/em&gt;, Volume 2, section 3.2.1.&#xA;The main benefit of LCGs is that constants can be chosen such that they&#xA;emit every possible output value once before repeating,&#xA;as the Unix implementation did for 15-bit outputs.&#xA;A serious problem with LCGs, however, is that the high bits of the state do not affect the low bits at all,&#xA;so every truncation of the sequence to &lt;em&gt;k&lt;/em&gt; bits necessarily repeats with a smaller period.&#xA;The low bit must toggle: 0, 1, 0, 1, 0, 1.&#xA;The low two bits must count up or down: 0, 1, 2, 3, 0, 1, 2, 3, or else 0, 3, 2, 1, 0, 3, 2, 1.&#xA;There are four possible three-bit sequences; the original Unix implementation repeats 0, 5, 6, 3, 4, 1, 2, 7.&#xA;(These problems can be avoided by reducing the value modulo a prime,&#xA;but that would have been quite expensive at the time.&#xA;See S. K. Park and K. W. Miller&amp;rsquo;s 1988 CACM paper&#xA;“&lt;a href=&#34;https://dl.acm.org/doi/10.1145/63039.63042&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Random number generators: good ones are hard to find&lt;/a&gt;”&#xA;for a short analysis&#xA;and the first chapter of Knuth Volume 2 for a longer one.)&lt;/p&gt;&#xA;&lt;p&gt;Even with these known problems,&#xA;the &lt;code&gt;srand&lt;/code&gt; and &lt;code&gt;rand&lt;/code&gt; functions were included in the first C standard,&#xA;and equivalent functionality was included in essentially every language since then.&#xA;LCGs were once the dominant implementation strategy,&#xA;although they&amp;rsquo;ve fallen off in popularity due to some important drawbacks.&#xA;One significant remaining use is &lt;a href=&#34;https://github.com/openjdk/jdk8u-dev/blob/master/jdk/src/share/classes/java/util/Random.java&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;java.util.Random&lt;/code&gt;&lt;/a&gt;,&#xA;which powers &lt;a href=&#34;https://github.com/openjdk/jdk8u-dev/blob/master/jdk/src/share/classes/java/util/Random.java&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;java.lang.Math.random&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Another thing you can see from the implementation above&#xA;is that the internal state is completely exposed by the result of &lt;code&gt;rand&lt;/code&gt;.&#xA;An observer who knows the algorithm and sees a single result&#xA;can easily compute all future results.&#xA;If you are running a server that calculates some random values&#xA;that become public and some random values that must stay secret,&#xA;using this kind of generator would be disastrous:&#xA;the secrets wouldn&amp;rsquo;t be secret.&lt;/p&gt;&#xA;&lt;p&gt;More modern random generators aren&amp;rsquo;t as terrible as the original Unix one,&#xA;but they&amp;rsquo;re still not completely unpredictable.&#xA;To make that point, next we will look at the original &lt;code&gt;math/rand&lt;/code&gt; generator from Go 1&#xA;and the PCG generator we added in &lt;code&gt;math/rand/v2&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-go-1-generator&#34;&gt;The Go 1 Generator&lt;/h2&gt;&#xA;&lt;p&gt;The generator used in Go 1&amp;rsquo;s &lt;code&gt;math/rand&lt;/code&gt; is an instance of what is called a&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Linear-feedback_shift_register&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;linear-feedback shift register&lt;/a&gt;.&#xA;The algorithm is based on an idea by George Marsaglia,&#xA;tweaked by Don Mitchell and Jim Reeds,&#xA;and further customized by Ken Thompson for Plan 9 and then Go.&#xA;It has no official name, so this post calls it the Go 1 generator.&lt;/p&gt;&#xA;&lt;p&gt;The Go 1 generator&amp;rsquo;s internal state is a slice &lt;code&gt;vec&lt;/code&gt; of 607 uint64s.&#xA;In that slice, there are two distinguished elements: &lt;code&gt;vec[606]&lt;/code&gt;, the last element, is called the “tap”,&#xA;and &lt;code&gt;vec[334]&lt;/code&gt; is called the “feed”.&#xA;To generate the next random number,&#xA;the generator adds the tap and the feed&#xA;to produce a value &lt;code&gt;x&lt;/code&gt;,&#xA;stores &lt;code&gt;x&lt;/code&gt; back into the feed,&#xA;shifts the entire slice one position to the right&#xA;(the tap moves to &lt;code&gt;vec[0]&lt;/code&gt; and &lt;code&gt;vec[i]&lt;/code&gt; moves to &lt;code&gt;vec[i+1]&lt;/code&gt;),&#xA;and returns &lt;code&gt;x&lt;/code&gt;.&#xA;The generator is called “linear feedback” because the tap is &lt;em&gt;added&lt;/em&gt; to the feed;&#xA;the entire state is a “shift register” because each step shifts the slice entries.&lt;/p&gt;&#xA;&lt;p&gt;Of course, actually moving every slice entry forward would be prohibitively expensive,&#xA;so instead the implementation leaves the slice data in place&#xA;and moves the tap and feed positions backward&#xA;on each step. The code looks like:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;func (r *rngSource) Uint64() uint64 {&#xA;    r.tap--&#xA;    if r.tap &amp;lt; 0 {&#xA;        r.tap += len(r.vec)&#xA;    }&#xA;&#xA;    r.feed--&#xA;    if r.feed &amp;lt; 0 {&#xA;        r.feed += len(r.vec)&#xA;    }&#xA;&#xA;    x := r.vec[r.feed] + r.vec[r.tap]&#xA;    r.vec[r.feed] = x&#xA;    return uint64(x)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Generating the next number is quite cheap: two subtractions, two conditional adds, two loads, one add, one store.&lt;/p&gt;&#xA;&lt;p&gt;Unfortunately, because the generator directly returns one slice element from its internal state vector,&#xA;reading 607 values from the generator completely exposes all its state.&#xA;With those values, you can predict all the future values, by filling in your own &lt;code&gt;vec&lt;/code&gt;&#xA;and then running the algorithm.&#xA;You can also recover all the previous values, by running the algorithm backward&#xA;(subtracting the tap from the feed and shifting the slice to the left).&lt;/p&gt;&#xA;&lt;p&gt;As a complete demonstration, here is an &lt;a href=&#34;/play/p/v0QdGjUAtzC&#34;&gt;insecure program&lt;/a&gt;&#xA;generating pseudorandom authentication&#xA;tokens along with code that predicts the next token given a sequence of earlier tokens.&#xA;As you can see, the Go 1 generator provides no security at all (nor was it meant to).&#xA;The quality of the generated numbers also depends on the initial setting of &lt;code&gt;vec&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-pcg-generator&#34;&gt;The PCG Generator&lt;/h2&gt;&#xA;&lt;p&gt;For &lt;code&gt;math/rand/v2&lt;/code&gt;, we wanted to provide a more modern statistical random generator&#xA;and settled on Melissa O&amp;rsquo;Neill&amp;rsquo;s PCG algorithm, published in 2014 in her paper&#xA;“&lt;a href=&#34;https://www.pcg-random.org/pdf/hmc-cs-2014-0905.pdf&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;PCG: A Family of Simple Fast Space-Efficient Statistically Good Algorithms for Random Number Generation&lt;/a&gt;”.&#xA;The exhaustive analysis in the paper can make it hard to notice at first glance how utterly trivial the generators are:&#xA;PCG is a post-processed 128-bit LCG.&lt;/p&gt;&#xA;&lt;p&gt;If the state &lt;code&gt;p.x&lt;/code&gt; were a &lt;code&gt;uint128&lt;/code&gt; (hypothetically), the code to compute the next value would be:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;const (&#xA;    pcgM = 0x2360ed051fc65da44385df649fccf645&#xA;    pcgA = 0x5851f42d4c957f2d14057b7ef767814f&#xA;)&#xA;&#xA;type PCG struct {&#xA;    x uint128&#xA;}&#xA;&#xA;func (p *PCG) Uint64() uint64 {&#xA;    p.x = p.x * pcgM + pcgA&#xA;    return scramble(p.x)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The entire state is a single 128-bit number,&#xA;and the update is a 128-bit multiply and add.&#xA;In the return statement, the &lt;code&gt;scramble&lt;/code&gt; function reduces the 128-bit state&#xA;down to a 64-bit state.&#xA;The original PCG used (again using a hypothetical &lt;code&gt;uint128&lt;/code&gt; type):&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;func scramble(x uint128) uint64 {&#xA;    return bits.RotateLeft(uint64(x&amp;gt;&amp;gt;64) ^ uint64(x), -int(x&amp;gt;&amp;gt;122))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;This code XORs the two halves of the 128-bit state together&#xA;and then rotates the result according to the top six bits of the state.&#xA;This version is called PCG-XSL-RR, for “xor shift low, right rotate”.&lt;/p&gt;&#xA;&lt;p&gt;Based on a &lt;a href=&#34;/issue/21835#issuecomment-739065688&#34;&gt;suggestion from O&amp;rsquo;Neill during proposal discussion&lt;/a&gt;,&#xA;Go&amp;rsquo;s PCG uses a new scramble function based on multiplication,&#xA;which mixes the bits more aggressively:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;func scramble(x uint128) uint64 {&#xA;    hi, lo := uint64(x&amp;gt;&amp;gt;64), uint64(x)&#xA;    hi ^= hi &amp;gt;&amp;gt; 32&#xA;    hi *= 0xda942042e4dd58b5&#xA;    hi ^= hi &amp;gt;&amp;gt; 48&#xA;    hi *= lo | 1&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;O&amp;rsquo;Neill calls PCG with this scrambler PCG-DXSM, for “double xorshift multiply.”&#xA;Numpy uses this form of PCG as well.&lt;/p&gt;&#xA;&lt;p&gt;Although PCG uses more computation to generate each value,&#xA;it uses significantly less state: two uint64s instead of 607.&#xA;It is also much less sensitive to the initial values of that state,&#xA;and &lt;a href=&#34;https://www.pcg-random.org/statistical-tests.html&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;it passes many statistical tests that other generators do not&lt;/a&gt;.&#xA;In many ways it is an ideal statistical generator.&lt;/p&gt;&#xA;&lt;p&gt;Even so, PCG is not unpredictable.&#xA;While the scrambling of bits to prepare the result does not&#xA;expose the state directly like in the LCG and Go 1 generators,&#xA;&lt;a href=&#34;https://pdfs.semanticscholar.org/4c5e/4a263d92787850edd011d38521966751a179.pdf&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;PCG-XSL-RR can still be be reversed&lt;/a&gt;,&#xA;and it would not be surprising if PCG-DXSM could too.&#xA;For secrets, we need something different.&lt;/p&gt;&#xA;&lt;h2 id=&#34;cryptographic-randomness&#34;&gt;Cryptographic Randomness&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;Cryptographic random numbers&lt;/em&gt; need to be utterly unpredictable&#xA;in practice, even to an observer who knows how they are generated&#xA;and has observed any number of previously generated values.&#xA;The safety of cryptographic protocols, secret keys, modern commerce,&#xA;online privacy, and more all critically depend on access to cryptographic&#xA;randomness.&lt;/p&gt;&#xA;&lt;p&gt;Providing cryptographic randomness is ultimately the job of the&#xA;operating system, which can gather true randomness from physical devices—timings&#xA;of the mouse, keyboard, disks, and network, and more recently&#xA;&lt;a href=&#34;https://web.archive.org/web/20141230024150/http://www.cryptography.com/public/pdf/Intel_TRNG_Report_20120312.pdf&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;electrical noise measured directly by the CPU itself&lt;/a&gt;.&#xA;Once the operating system has gathered a meaningful&#xA;amount of randomness—say, at least 256 bits—it can use cryptographic&#xA;hashing or encryption algorithms to stretch that seed into&#xA;an arbitrarily long sequence of random numbers.&#xA;(In practice the operating system is also constantly gathering and&#xA;adding new randomness to the sequence too.)&lt;/p&gt;&#xA;&lt;p&gt;The exact operating system interfaces have evolved over time.&#xA;A decade ago, most systems provided a device file named&#xA;&lt;code&gt;/dev/random&lt;/code&gt; or something similar.&#xA;Today, in recognition of how fundamental randomness has become,&#xA;operating systems provide a direct system call instead.&#xA;(This also allows programs to read randomness even&#xA;when cut off from the file system.)&#xA;In Go, the &lt;a href=&#34;/pkg/crypto/rand/&#34;&gt;&lt;code&gt;crypto/rand&lt;/code&gt;&lt;/a&gt; package abstracts away those details,&#xA;providing the same interface on every operating system: &lt;a href=&#34;/pkg/crypto/rand/#Read&#34;&gt;&lt;code&gt;rand.Read&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;It would not be practical for &lt;code&gt;math/rand&lt;/code&gt; to ask the operating system for&#xA;randomness each time it needs a &lt;code&gt;uint64&lt;/code&gt;.&#xA;But we can use cryptographic techniques to define an in-process&#xA;random generator that improves on LCGs, the Go 1 generator, and even PCG.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-chacha8rand-generator&#34;&gt;The ChaCha8Rand Generator&lt;/h2&gt;&#xA;&lt;p&gt;Our new generator, which we unimaginatively named ChaCha8Rand for specification purposes&#xA;and implemented as &lt;code&gt;math/rand/v2&lt;/code&gt;&amp;rsquo;s &lt;a href=&#34;/pkg/math/rand/v2/#ChaCha8&#34;&gt;&lt;code&gt;rand.ChaCha8&lt;/code&gt;&lt;/a&gt;,&#xA;is a lightly modified version of Daniel J. Bernstein&amp;rsquo;s &lt;a href=&#34;https://cr.yp.to/chacha.html&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;ChaCha stream cipher&lt;/a&gt;.&#xA;ChaCha is widely used in a 20-round form called ChaCha20, including in TLS and SSH.&#xA;Jean-Philippe Aumasson&amp;rsquo;s paper “&lt;a href=&#34;https://eprint.iacr.org/2019/1492.pdf&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Too Much Crypto&lt;/a&gt;”&#xA;argues persuasively that the 8-round form ChaCha8 is secure too (and it&amp;rsquo;s roughly 2.5X faster).&#xA;We used ChaCha8 as the core of ChaCha8Rand.&lt;/p&gt;&#xA;&lt;p&gt;Most stream ciphers, including ChaCha8, work by defining a function that is given&#xA;a key and a block number and produces a fixed-size block of apparently random data.&#xA;The cryptographic standard these aim for (and usually meet) is for this output to be indistinguishable&#xA;from actual random data in the absence of some kind of exponentially costly brute force search.&#xA;A message is encrypted or decrypted by XOR&amp;rsquo;ing successive blocks of input data&#xA;with successive randomly generated blocks.&#xA;To use ChaCha8 as a &lt;code&gt;rand.Source&lt;/code&gt;,&#xA;we use the generated blocks directly instead of XOR&amp;rsquo;ing them with input data&#xA;(this is equivalent to encrypting or decrypting all zeros).&lt;/p&gt;&#xA;&lt;p&gt;We changed a few details to make ChaCha8Rand more suitable for generating random numbers. Briefly:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;ChaCha8Rand takes a 32-byte seed, used as the ChaCha8 key.&lt;/li&gt;&#xA;&lt;li&gt;ChaCha8 generates 64-byte blocks, with calculations treating a block as 16 &lt;code&gt;uint32&lt;/code&gt;s.&#xA;A common implementation is to compute four blocks at a time using &lt;a href=&#34;https://en.wikipedia.org/wiki/Single_instruction,_multiple_data&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;SIMD instructions&lt;/a&gt;&#xA;on 16 vector registers of four &lt;code&gt;uint32&lt;/code&gt;s each.&#xA;This produces four interleaved blocks that must be unshuffled for XOR&amp;rsquo;ing with the input data.&#xA;ChaCha8Rand defines that the interleaved blocks are the random data stream,&#xA;removing the cost of the unshuffle.&#xA;(For security purposes, this can be viewed as standard ChaCha8 followed by a reshuffle.)&lt;/li&gt;&#xA;&lt;li&gt;ChaCha8 finishes a block by adding certain values to each &lt;code&gt;uint32&lt;/code&gt; in the block.&#xA;Half the values are key material and the other half are known constants.&#xA;ChaCha8Rand defines that the known constants are not re-added,&#xA;removing half of the final adds.&#xA;(For security purposes, this can be viewed as standard ChaCha8 followed by subtracting the known constants.)&lt;/li&gt;&#xA;&lt;li&gt;Every 16th generated block, ChaCha8Rand takes the final 32 bytes of the block for itself,&#xA;making them the key for the next 16 blocks.&#xA;This provides a kind of &lt;a href=&#34;https://en.wikipedia.org/wiki/Forward_secrecy&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;forward secrecy&lt;/a&gt;:&#xA;if a system is compromised by an attack that&#xA;recovers the entire memory state of the generator, only values generated&#xA;since the last rekeying can be recovered. The past is inaccessible.&#xA;ChaCha8Rand as defined so far must generate 4 blocks at a time,&#xA;but we chose to do this key rotation every 16 blocks to leave open the&#xA;possibility of faster implementations using 256-bit or 512-bit vectors,&#xA;which could generate 8 or 16 blocks at a time.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;We wrote and published a &lt;a href=&#34;https://c2sp.org/chacha8rand&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;C2SP specification for ChaCha8Rand&lt;/a&gt;,&#xA;along with test cases.&#xA;This will enable other implementations to share repeatability with the Go implementation&#xA;for a given seed.&lt;/p&gt;&#xA;&lt;p&gt;The Go runtime now maintains a per-core ChaCha8Rand state (300 bytes),&#xA;seeded with operating system-supplied cryptographic randomness,&#xA;so that random numbers can be generated quickly without any lock contention.&#xA;Dedicating 300 bytes per core may sound expensive,&#xA;but on a 16-core system, it is about the same as storing a single shared Go 1 generator state (4,872 bytes).&#xA;The speed is worth the memory.&#xA;This per-core ChaCha8Rand generator is now used in three different places in the Go standard library:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The &lt;code&gt;math/rand/v2&lt;/code&gt; package functions, such as&#xA;&lt;a href=&#34;/pkg/math/rand/v2/#Float64&#34;&gt;&lt;code&gt;rand.Float64&lt;/code&gt;&lt;/a&gt; and&#xA;&lt;a href=&#34;/pkg/math/rand/v2/#N&#34;&gt;&lt;code&gt;rand.N&lt;/code&gt;&lt;/a&gt;, always use ChaCha8Rand.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The &lt;code&gt;math/rand&lt;/code&gt; package functions, such as&#xA;&lt;a href=&#34;/pkg/math/rand/#Float64&#34;&gt;&lt;code&gt;rand.Float64&lt;/code&gt;&lt;/a&gt; and&#xA;&lt;a href=&#34;/pkg/math/rand/#Intn&#34;&gt;&lt;code&gt;rand.Intn&lt;/code&gt;&lt;/a&gt;,&#xA;use ChaCha8Rand when&#xA;&lt;a href=&#34;/pkg/math/rand/#Seed&#34;&gt;&lt;code&gt;rand.Seed&lt;/code&gt;&lt;/a&gt; has not been called.&#xA;Applying ChaCha8Rand in &lt;code&gt;math/rand&lt;/code&gt; improves the security of programs&#xA;even before they update to &lt;code&gt;math/rand/v2&lt;/code&gt;,&#xA;provided they are not calling &lt;code&gt;rand.Seed&lt;/code&gt;.&#xA;(If &lt;code&gt;rand.Seed&lt;/code&gt; is called, the implementation is required to fall back to the Go 1 generator for compatibility.)&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The runtime chooses the hash seed for each new map&#xA;using ChaCha8Rand instead of a less secure &lt;a href=&#34;https://github.com/wangyi-fudan/wyhash&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;wyrand-based generator&lt;/a&gt;&#xA;it previously used.&#xA;Random seeds are needed because if&#xA;an attacker knows the specific hash function used by a map implementation,&#xA;they can prepare input that drives the map into quadratic behavior&#xA;(see Crosby and Wallach&amp;rsquo;s “&lt;a href=&#34;https://www.usenix.org/conference/12th-usenix-security-symposium/denial-service-algorithmic-complexity-attacks&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Denial of Service via Algorithmic Complexity Attacks&lt;/a&gt;”).&#xA;Using a per-map seed, instead of one global seed for all maps,&#xA;also avoids &lt;a href=&#34;https://accidentallyquadratic.tumblr.com/post/153545455987/rust-hash-iteration-reinsertion&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;other degenerate behaviors&lt;/a&gt;.&#xA;It is not strictly clear that maps need a cryptographically random seed,&#xA;but it&amp;rsquo;s also not clear that they don&amp;rsquo;t. It seemed prudent and was trivial to switch.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Code that needs its own ChaCha8Rand instances can create its own &lt;a href=&#34;/pkg/math/rand/v2/#ChaCha8&#34;&gt;&lt;code&gt;rand.ChaCha8&lt;/code&gt;&lt;/a&gt; directly.&lt;/p&gt;&#xA;&lt;h2 id=&#34;fixing-security-mistakes&#34;&gt;Fixing Security Mistakes&lt;/h2&gt;&#xA;&lt;p&gt;Go aims to help developers write code that is secure by default.&#xA;When we observe a common mistake with security consequences,&#xA;we look for ways to reduce the risk of that mistake&#xA;or eliminate it entirely.&#xA;In this case, &lt;code&gt;math/rand&lt;/code&gt;&amp;rsquo;s global generator was far too predictable,&#xA;leading to serious problems in a variety of contexts.&lt;/p&gt;&#xA;&lt;p&gt;For example, when Go 1.20 deprecated &lt;a href=&#34;/pkg/math/rand/#Read&#34;&gt;&lt;code&gt;math/rand&lt;/code&gt;’s &lt;code&gt;Read&lt;/code&gt;&lt;/a&gt;,&#xA;we heard from developers who discovered (thanks to tooling pointing out&#xA;use of deprecated functionality) they had been&#xA;using it in places where &lt;a href=&#34;/pkg/crypto/rand/#Read&#34;&gt;&lt;code&gt;crypto/rand&lt;/code&gt;’s &lt;code&gt;Read&lt;/code&gt;&lt;/a&gt;&#xA;was definitely needed, like generating key material.&#xA;Using Go 1.20, that mistake&#xA;is a serious security problem that merits a detailed investigation&#xA;to understand the damage.&#xA;Where were the keys used?&#xA;How were the keys exposed?&#xA;Were other random outputs exposed that might allow an attacker to derive the keys?&#xA;And so on.&#xA;Using Go 1.22, that mistake is just a mistake.&#xA;It&amp;rsquo;s still better to use &lt;code&gt;crypto/rand&lt;/code&gt;,&#xA;because the operating system kernel can do a better job keeping the random values&#xA;secret from various kinds of prying eyes,&#xA;the kernel is continually adding new entropy to its generator,&#xA;and the kernel has had more scrutiny.&#xA;But accidentally using &lt;code&gt;math/rand&lt;/code&gt; is no longer a security catastrophe.&lt;/p&gt;&#xA;&lt;p&gt;There are also a variety of use cases that don&amp;rsquo;t seem like “crypto”&#xA;but nonetheless need unpredictable randomness.&#xA;These cases are made more robust by using ChaCha8Rand instead of the Go 1 generator.&lt;/p&gt;&#xA;&lt;p&gt;For example, consider generating a&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;random UUID&lt;/a&gt;.&#xA;Since UUIDs are not secret, using &lt;code&gt;math/rand&lt;/code&gt; might seem fine.&#xA;But if &lt;code&gt;math/rand&lt;/code&gt; has been seeded with the current time,&#xA;then running it at the same instant on different computers&#xA;will produce the same value, making them not “universally unique”.&#xA;This is especially likely on systems where the current time&#xA;is only available with millisecond precision.&#xA;Even with auto-seeding using OS-provided entropy,&#xA;as introduced in Go 1.20,&#xA;the Go 1 generator&amp;rsquo;s seed is only a 63-bit integer,&#xA;so a program that generates a UUID at startup&#xA;can only generate 2⁶³ possible UUIDs and is&#xA;likely to see collisions after 2³¹ or so UUIDs.&#xA;Using Go 1.22, the new ChaCha8Rand generator&#xA;is seeded from 256 bits of entropy and can generate&#xA;2²⁵⁶ possible first UUIDs.&#xA;It does not need to worry about collisions.&lt;/p&gt;&#xA;&lt;p&gt;As another example, consider load balancing in a front-end server&#xA;that randomly assigns incoming requests to back-end servers.&#xA;If an attacker can observe the assignments and knows the&#xA;predictable algorithm generating them,&#xA;then the attacker could send a stream&#xA;of mostly cheap requests but arrange for all the expensive requests&#xA;to land on a single back-end server.&#xA;This is an unlikely but plausible problem using the Go 1 generator.&#xA;Using Go 1.22, it&amp;rsquo;s not a problem at all.&lt;/p&gt;&#xA;&lt;p&gt;In all these examples, Go 1.22 has eliminated or greatly reduced&#xA;security problems.&lt;/p&gt;&#xA;&lt;h2 id=&#34;performance&#34;&gt;Performance&lt;/h2&gt;&#xA;&lt;p&gt;The security benefits of ChaCha8Rand do have a small cost,&#xA;but ChaCha8Rand is still in the same ballpark as both the Go 1 generator and PCG.&#xA;The following graphs compare the performance of the three generators,&#xA;across a variety of hardware, running two operations:&#xA;the primitive operation “Uint64,” which returns the next &lt;code&gt;uint64&lt;/code&gt; in the random stream,&#xA;and the higher-level operation “N(1000),” which returns a random value in the range [0, 1000).&lt;/p&gt;&#xA;&lt;div style=&#34;background-color: white;&#34;&gt;&#xA;&lt;img src=&#34;chacha8rand/amd.svg&#34;&gt;&#xA;&lt;img src=&#34;chacha8rand/intel.svg&#34;&gt;&#xA;&lt;img src=&#34;chacha8rand/amd32.svg&#34;&gt;&#xA;&lt;img src=&#34;chacha8rand/intel32.svg&#34;&gt;&#xA;&lt;img src=&#34;chacha8rand/m1.svg&#34;&gt;&#xA;&lt;img src=&#34;chacha8rand/m3.svg&#34;&gt;&#xA;&lt;img src=&#34;chacha8rand/taut2a.svg&#34;&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;The “running 32-bit code” graphs show modern 64-bit x86 chips&#xA;executing code built with &lt;code&gt;GOARCH=386&lt;/code&gt;, meaning they are&#xA;running in 32-bit mode.&#xA;In that case, the fact that PCG requires 128-bit multiplications&#xA;makes it slower than ChaCha8Rand, which only uses 32-bit SIMD arithmetic.&#xA;Actual 32-bit systems matter less every year,&#xA;but it is still interesting that ChaCha8Rand is faster than PCG&#xA;on those systems.&lt;/p&gt;&#xA;&lt;p&gt;On some systems, “Go 1: Uint64” is faster than “PCG: Uint64”,&#xA;but “Go 1: N(1000)” is slower than “PCG: N(1000)”.&#xA;This happens because “Go 1: N(1000)” is using &lt;code&gt;math/rand&lt;/code&gt;&amp;rsquo;s algorithm for&#xA;reducing a random &lt;code&gt;int64&lt;/code&gt; down to a value in the range [0, 1000),&#xA;and that algorithm does two 64-bit integer divide operations.&#xA;In contrast, “PCG: N(1000)” and “ChaCha8: N(1000)” use the &lt;a href=&#34;/blog/randv2#problem.rand&#34;&gt;faster &lt;code&gt;math/rand/v2&lt;/code&gt; algorithm&lt;/a&gt;,&#xA;which almost always avoids the divisions.&#xA;Removing the 64-bit divisions dominates the algorithm change&#xA;for 32-bit execution and on the Ampere.&lt;/p&gt;&#xA;&lt;p&gt;Overall, ChaCha8Rand is slower than the Go 1 generator,&#xA;but it is never more than twice as slow, and on typical servers the&#xA;difference is never more than 3ns.&#xA;Very few programs will be bottlenecked by this difference,&#xA;and many programs will enjoy the improved security.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;Go 1.22 makes your programs more secure without any code changes.&#xA;We did this by identifying the common mistake of accidentally using &lt;code&gt;math/rand&lt;/code&gt;&#xA;instead of &lt;code&gt;crypto/rand&lt;/code&gt; and then strengthening &lt;code&gt;math/rand&lt;/code&gt;.&#xA;This is one small step in Go&amp;rsquo;s ongoing journey to keep programs&#xA;safe by default.&lt;/p&gt;&#xA;&lt;p&gt;These kinds of mistakes are not unique to Go.&#xA;For example, the npm &lt;code&gt;keypair&lt;/code&gt; package tries to generate an RSA key pair&#xA;using Web Crypto APIs, but if they&amp;rsquo;re not available, it falls back to JavaScript&amp;rsquo;s &lt;code&gt;Math.random&lt;/code&gt;.&#xA;This is hardly an isolated case,&#xA;and the security of our systems cannot depend on developers not making mistakes.&#xA;Instead, we hope that eventually all programming languages&#xA;will move to cryptographically strong pseudorandom generators&#xA;even for “mathematical” randomness,&#xA;eliminating this kind of mistake, or at least greatly reducing its blast radius.&#xA;Go 1.22&amp;rsquo;s &lt;a href=&#34;https://c2sp.org/chacha8rand&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;ChaCha8Rand&lt;/a&gt; implementation&#xA;proves that this approach is competitive with other generators.&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;Article prevnext&#34;&gt;&#xA;    &#xA;    &#xA;      &#xA;        &lt;p&gt;&#xA;        &#xA;        &#xA;          &#xA;            &lt;b&gt;Previous article: &lt;/b&gt;&lt;a href=&#34;/blog/randv2&#34;&gt;Evolving the Go Standard Library with math/rand/v2&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &lt;b&gt;&lt;a href=&#34;/blog/all&#34;&gt;Blog Index&lt;/a&gt;&lt;/b&gt;&#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;    &lt;/div&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script src=&#34;/js/jquery.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/playground.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/play.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/godocs.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;</content></entry><entry><title>Evolving the Go Standard Library with math/rand/v2</title><id>tag:blog.golang.org,2013:blog.golang.org/randv2</id><link rel="alternate" href="https://go.dev/blog/randv2"></link><published>2024-05-01T00:00:00+00:00</published><updated>2024-05-01T00:00:00+00:00</updated><author><name></name></author><summary type="html">Go 1.22 adds math/rand/v2 and charts a course for the evolution of the Go standard library.</summary><content type="html">&#xA;&lt;div id=&#34;blog&#34;&gt;&lt;div id=&#34;content&#34;&gt;&#xA;  &lt;div id=&#34;content&#34;&gt;&#xA;&#xA;    &lt;div class=&#34;Article&#34; data-slug=&#34;/blog/randv2&#34;&gt;&#xA;    &#xA;    &lt;h1 class=&#34;small&#34;&gt;&lt;a href=&#34;/blog/&#34;&gt;The Go Blog&lt;/a&gt;&lt;/h1&gt;&#xA;    &#xA;&#xA;    &lt;h1&gt;Evolving the Go Standard Library with math/rand/v2&lt;/h1&gt;&#xA;      &#xA;      &lt;p class=&#34;author&#34;&gt;&#xA;      Russ Cox&lt;br&gt;&#xA;      1 May 2024&#xA;      &lt;/p&gt;&#xA;      &#xA;      &lt;p&gt;Since Go 1 was &lt;a href=&#34;/blog/go1&#34;&gt;released in March 2012&lt;/a&gt;,&#xA;changes to the standard library have been&#xA;constrained by Go&amp;rsquo;s &lt;a href=&#34;/doc/go1compat&#34;&gt;compatibility promise&lt;/a&gt;.&#xA;Overall, compatibility has been a boon for Go users,&#xA;providing a stable base for production systems,&#xA;documentation, tutorials, books, and more.&#xA;Over time, however, we&amp;rsquo;ve realized mistakes in the original APIs&#xA;that cannot be fixed compatibly; in other cases,&#xA;best practices and convention have changed.&#xA;We need a plan for making important, breaking changes too.&lt;/p&gt;&#xA;&lt;p&gt;This blog post is about Go 1.22&amp;rsquo;s new &lt;a href=&#34;/pkg/math/rand/v2/&#34;&gt;&lt;code&gt;math/rand/v2&lt;/code&gt;&lt;/a&gt; package,&#xA;the first “v2” in the standard library.&#xA;It brings needed improvements to the &lt;a href=&#34;/pkg/math/rand/&#34;&gt;&lt;code&gt;math/rand&lt;/code&gt;&lt;/a&gt; API,&#xA;but more importantly it sets an example for how we can&#xA;revise other standard library packages as the need arises.&lt;/p&gt;&#xA;&lt;p&gt;(In Go, &lt;code&gt;math/rand&lt;/code&gt; and &lt;code&gt;math/rand/v2&lt;/code&gt; are two different packages&#xA;with different import paths.&#xA;Go 1 and every release after it have included &lt;code&gt;math/rand&lt;/code&gt;; Go 1.22 added &lt;code&gt;math/rand/v2&lt;/code&gt;.&#xA;A Go program can import either package, or both.)&lt;/p&gt;&#xA;&lt;p&gt;This post discusses the specific rationale for the changes in &lt;code&gt;math/rand/v2&lt;/code&gt;&#xA;and then &lt;a href=&#34;#principles&#34;&gt;reflects on the general principles&lt;/a&gt; that will guide&#xA;new versions of other packages.&lt;/p&gt;&#xA;&lt;h2 id=&#34;pseudo&#34;&gt;Pseudorandom Number Generators&lt;/h2&gt;&#xA;&lt;p&gt;Before we look at &lt;code&gt;math/rand&lt;/code&gt;, which is an API for a pseudorandom number generator,&#xA;let&amp;rsquo;s take a moment to understand what that means.&lt;/p&gt;&#xA;&lt;p&gt;A pseudorandom number generator is a deterministic program&#xA;that generates a long sequence of&#xA;seemingly random numbers from a small seed input,&#xA;although the numbers are not in fact random at all.&#xA;In the case of &lt;code&gt;math/rand&lt;/code&gt;, the seed is a single int64,&#xA;and the algorithm produces a sequence of int64s&#xA;using a variant of a&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Linear-feedback_shift_register&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;linear-feedback shift register (LFSR)&lt;/a&gt;.&#xA;The algorithm is based on an idea by George Marsaglia,&#xA;tweaked by Don Mitchell and Jim Reeds,&#xA;and further customized by Ken Thompson for Plan 9 and then Go.&#xA;It has no official name, so this post calls it the Go 1 generator.&lt;/p&gt;&#xA;&lt;p&gt;The goal is for these generators to be fast,&#xA;repeatable, and random enough to support simulations,&#xA;shuffling, and other non-cryptographic use cases.&#xA;Repeatability is particularly important for uses like&#xA;numerical simulations or randomized testing.&#xA;For example, a randomized tester might pick a seed&#xA;(perhaps based on the current time), generate&#xA;a large random test input, and repeat.&#xA;When the tester finds a failure, it only needs to print the seed&#xA;to allow repeating the test with that specific large input.&lt;/p&gt;&#xA;&lt;p&gt;Repeatability also matters over time: given a particular&#xA;seed, a new version of Go needs to generate the same&#xA;sequence of values that an older version did.&#xA;We didn&amp;rsquo;t realize this when we released Go 1;&#xA;instead, we discovered it the hard way,&#xA;when we tried to make a change in Go 1.2&#xA;and got reports that we had broken certain tests&#xA;and other use cases.&#xA;At that point, we decided Go 1 compatibility included&#xA;the specific random outputs for a given seed&#xA;and &lt;a href=&#34;/change/5aca0514941ce7dd0f3cea8d8ffe627dbcd542ca&#34;&gt;added a test&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;It is not a goal for these kinds of generators to produce&#xA;random numbers suitable for deriving cryptographic keys&#xA;or other important secrets.&#xA;Because the seed is only 63 bits,&#xA;any output drawn from the generator, no matter how long,&#xA;will also only contain 63 bits of entropy.&#xA;For example, using &lt;code&gt;math/rand&lt;/code&gt; to generate a 128-bit or 256-bit AES key&#xA;would be a serious mistake,&#xA;since the key would be easier to brute force.&#xA;For that kind of use, you need a cryptographically strong&#xA;random number generator, as provided by &lt;a href=&#34;/pkg/crypto/rand/&#34;&gt;&lt;code&gt;crypto/rand&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s enough background that we can move on to what needed&#xA;fixing in the &lt;code&gt;math/rand&lt;/code&gt; package.&lt;/p&gt;&#xA;&lt;h2 id=&#34;problems&#34;&gt;Problems with &lt;code&gt;math/rand&lt;/code&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Over time, we noticed more and more problems with &lt;code&gt;math/rand&lt;/code&gt;.&#xA;The most serious were the following.&lt;/p&gt;&#xA;&lt;h3 id=&#34;problem.generator&#34;&gt;Generator Algorithm&lt;/h3&gt;&#xA;&lt;p&gt;The generator itself needed replacement.&lt;/p&gt;&#xA;&lt;p&gt;The initial implementation of Go, while production ready, was in many ways a “pencil sketch”&#xA;of the entire system, working well enough to serve as a base for future development:&#xA;the compiler and runtime were written in C; the garbage collector was a conservative, single-threaded,&#xA;stop-the-world collector; and the libraries used basic implementations throughout.&#xA;From Go 1 through around Go 1.5, we went back and drew the “fully inked”&#xA;version of each of these: we converted the compiler and runtime to Go; we wrote a new, precise, parallel,&#xA;concurrent garbage collection with microsecond pause times; and we replaced&#xA;standard library implementations with more sophisticated, optimized algorithms&#xA;as needed.&lt;/p&gt;&#xA;&lt;p&gt;Unfortunately, the repeatability requirement in &lt;code&gt;math/rand&lt;/code&gt;&#xA;meant that we couldn&amp;rsquo;t replace the generator there without&#xA;breaking compatibility.&#xA;We were stuck with the Go 1 generator,&#xA;which is reasonably fast (about 1.8ns per number on my M3 Mac)&#xA;but maintains an internal state of almost 5 kilobytes.&#xA;In contrast, Melissa O&amp;rsquo;Neill&amp;rsquo;s &lt;a href=&#34;https://www.pcg-random.org/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;PCG family of generators&lt;/a&gt;&#xA;generates better random numbers in about 2.1ns per number&#xA;with only 16 bytes of internal state.&#xA;We also wanted to explore using&#xA;Daniel J. Bernstein&amp;rsquo;s &lt;a href=&#34;https://cr.yp.to/chacha.html&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;ChaCha stream cipher&lt;/a&gt;&#xA;as a generator.&#xA;A &lt;a href=&#34;/blog/chacha8rand&#34;&gt;follow-up post&lt;/a&gt; discusses that generator specifically.&lt;/p&gt;&#xA;&lt;h3 id=&#34;problem.source&#34;&gt;Source Interface&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;/pkg/math/rand/#Source&#34;&gt;&lt;code&gt;rand.Source&lt;/code&gt; interface&lt;/a&gt; was wrong.&#xA;That interface defines the&#xA;concept of a low-level random number generator that generates&#xA;non-negative &lt;code&gt;int64&lt;/code&gt; values:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;% go doc -src math/rand.Source&#xA;package rand // import &amp;quot;math/rand&amp;quot;&#xA;&#xA;// A Source represents a source of uniformly-distributed&#xA;// pseudo-random int64 values in the range [0, 1&amp;lt;&amp;lt;63).&#xA;//&#xA;// A Source is not safe for concurrent use by multiple goroutines.&#xA;type Source interface {&#xA;    Int63() int64&#xA;    Seed(seed int64)&#xA;}&#xA;&#xA;func NewSource(seed int64) Source&#xA;%&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;(In the doc comment, “[0, N)” denotes a&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Interval_(mathematics)#Definitions_and_terminology&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;half-open interval&lt;/a&gt;,&#xA;meaning the range includes 0 but ends just before 2⁶³.)&lt;/p&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;/pkg/math/rand/#Rand&#34;&gt;&lt;code&gt;rand.Rand&lt;/code&gt; type&lt;/a&gt; wraps a &lt;code&gt;Source&lt;/code&gt;&#xA;to implement a richer set of operations, such as&#xA;generating &lt;a href=&#34;/pkg/math/rand/#Rand.Intn&#34;&gt;an integer between 0 and N&lt;/a&gt;,&#xA;generating &lt;a href=&#34;/pkg/math/rand/#Rand.Float64&#34;&gt;floating-point numbers&lt;/a&gt;, and so on.&lt;/p&gt;&#xA;&lt;p&gt;We defined the &lt;code&gt;Source&lt;/code&gt; interface to return a shortened 63-bit value&#xA;instead of a uint64 because that&amp;rsquo;s what the Go 1 generator and&#xA;other widely-used generators produce,&#xA;and it matches the convention set by the C standard library.&#xA;But this was a mistake: more modern generators produce full-width uint64s,&#xA;which is a more convenient interface.&lt;/p&gt;&#xA;&lt;p&gt;Another problem is the &lt;code&gt;Seed&lt;/code&gt; method hard-coding an &lt;code&gt;int64&lt;/code&gt; seed:&#xA;some generators are seeded by larger values,&#xA;and the interface provides no way to handle that.&lt;/p&gt;&#xA;&lt;h3 id=&#34;problem.seed&#34;&gt;Seeding Responsibility&lt;/h3&gt;&#xA;&lt;p&gt;A bigger problem with &lt;code&gt;Seed&lt;/code&gt; is that responsibility for seeding the global generator was unclear.&#xA;Most users don&amp;rsquo;t use &lt;code&gt;Source&lt;/code&gt; and &lt;code&gt;Rand&lt;/code&gt; directly.&#xA;Instead, the &lt;code&gt;math/rand&lt;/code&gt; package provides a global generator&#xA;accessed by top-level functions like &lt;a href=&#34;/pkg/math/rand/#Intn&#34;&gt;&lt;code&gt;Intn&lt;/code&gt;&lt;/a&gt;.&#xA;Following the C standard library, the global generator defaults to&#xA;behaving as if &lt;code&gt;Seed(1)&lt;/code&gt; is called at startup.&#xA;This is good for repeatability but bad for programs that want&#xA;their random outputs to be different from one run to the next.&#xA;The package documentation suggests using &lt;code&gt;rand.Seed(time.Now().UnixNano())&lt;/code&gt; in that case,&#xA;to make the generator&amp;rsquo;s output time-dependent,&#xA;but what code should do this?&lt;/p&gt;&#xA;&lt;p&gt;Probably the main package should be in charge of how &lt;code&gt;math/rand&lt;/code&gt; is seeded:&#xA;it would be unfortunate for imported libraries to configure global state themselves,&#xA;since their choices might conflict with other libraries or the main package.&#xA;But what happens if a library needs some random data and wants to use &lt;code&gt;math/rand&lt;/code&gt;?&#xA;What if the main package doesn&amp;rsquo;t even know &lt;code&gt;math/rand&lt;/code&gt; is being used?&#xA;We found that in practice many libraries add init functions&#xA;that seed the global generator with the current time, “just to be sure”.&lt;/p&gt;&#xA;&lt;p&gt;Library packages seeding the global generator themselves causes a new problem.&#xA;Suppose package main imports two packages that both use &lt;code&gt;math/rand&lt;/code&gt;:&#xA;package A assumes the global generator will be seeded by package main,&#xA;but package B seeds it in an &lt;code&gt;init&lt;/code&gt; func.&#xA;And suppose that package main doesn&amp;rsquo;t seed the generator itself.&#xA;Now package A&amp;rsquo;s correct operation depends on the coincidence that package B is also&#xA;imported in the program.&#xA;If package main stops importing package B, package A will stop getting random values.&#xA;We observed this happening in practice in large codebases.&lt;/p&gt;&#xA;&lt;p&gt;In retrospect, it was clearly a mistake to follow the C standard library here:&#xA;seeding the global generator automatically would remove the confusion&#xA;about who seeds it, and users would stop being surprised by repeatable&#xA;output when they didn&amp;rsquo;t want that.&lt;/p&gt;&#xA;&lt;h3 id=&#34;problem.scale&#34;&gt;Scalability&lt;/h3&gt;&#xA;&lt;p&gt;The global generator also did not scale well.&#xA;Because top-level functions like &lt;a href=&#34;/pkg/math/rand/#Intn&#34;&gt;&lt;code&gt;rand.Intn&lt;/code&gt;&lt;/a&gt;&#xA;can be called simultaneously from multiple goroutines,&#xA;the implementation needed a lock protecting the shared generator state.&#xA;In parallel usage, acquiring and releasing this lock was more expensive&#xA;than the actual generation.&#xA;It would make sense instead to have a per-thread generator state,&#xA;but doing so would break repeatability&#xA;in programs without concurrent use of &lt;code&gt;math/rand&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;problem.rand&#34;&gt;The &lt;code&gt;Rand&lt;/code&gt; implementation was missing important optimizations&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;/pkg/math/rand/#Rand&#34;&gt;&lt;code&gt;rand.Rand&lt;/code&gt; type&lt;/a&gt; wraps a &lt;code&gt;Source&lt;/code&gt;&#xA;to implement a richer set of operations&#xA;For example, here is the Go 1 implementation of &lt;code&gt;Int63n&lt;/code&gt;, which returns&#xA;a random integer in the range [0, &lt;code&gt;n&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;func (r *Rand) Int63n(n int64) int64 {&#xA;    if n &amp;lt;= 0 {&#xA;        panic(&amp;quot;invalid argument to Int63n&amp;quot;)&#xA;    }&#xA;    max := int64((1&amp;lt;&amp;lt;63 - 1)  - (1&amp;lt;&amp;lt;63)%uint64(n))&#xA;    v := r.src.Int63()&#xA;    for v &amp;gt; max {&#xA;        v = r.Int63()&#xA;    }&#xA;    return v % n&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The actual conversion is easy: &lt;code&gt;v % n&lt;/code&gt;.&#xA;However, no algorithm can convert 2⁶³ equally likely values&#xA;into &lt;code&gt;n&lt;/code&gt; equally likely values unless 2⁶³ is a multiple of &lt;code&gt;n&lt;/code&gt;:&#xA;otherwise some outputs will necessarily happen more often&#xA;than others. (As a simpler example, try converting 4 equally likely values into 3.)&#xA;The code computes &lt;code&gt;max&lt;/code&gt; such that&#xA;&lt;code&gt;max+1&lt;/code&gt; is the largest multiple of &lt;code&gt;n&lt;/code&gt; less than or equal to 2⁶³,&#xA;and then the loop rejects random values greater than or equal to &lt;code&gt;max+1&lt;/code&gt;.&#xA;Rejecting this too-large values ensures that all &lt;code&gt;n&lt;/code&gt; outputs are equally likely.&#xA;For small &lt;code&gt;n&lt;/code&gt;, needing to reject any value at all is rare;&#xA;rejection becomes more common and more important for larger values.&#xA;Even without the rejection loop, the two (slow) modulus operations&#xA;can make the conversion more expensive than generating the random value &lt;code&gt;v&lt;/code&gt;&#xA;in the first place.&lt;/p&gt;&#xA;&lt;p&gt;In 2018, &lt;a href=&#34;https://arxiv.org/abs/1805.10941&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Daniel Lemire found an algorithm&lt;/a&gt;&#xA;that avoids the divisions nearly all the time&#xA;(see also his &lt;a href=&#34;https://lemire.me/blog/2019/06/06/nearly-divisionless-random-integer-generation-on-various-systems/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;2019 blog post&lt;/a&gt;).&#xA;In &lt;code&gt;math/rand&lt;/code&gt;, adopting Lemire&amp;rsquo;s algorithm would make &lt;code&gt;Intn(1000)&lt;/code&gt; 20-30% faster,&#xA;but we can&amp;rsquo;t: the faster algorithm generates different values than the standard conversion,&#xA;breaking repeatability.&lt;/p&gt;&#xA;&lt;p&gt;Other methods are also slower than they could be, constrained by repeatability.&#xA;For example, the &lt;code&gt;Float64&lt;/code&gt; method could easily be sped up by about 10%&#xA;if we could change the generated value stream.&#xA;(This was the change we tried to make in Go 1.2 and rolled back, mentioned earlier.)&lt;/p&gt;&#xA;&lt;h3 id=&#34;problem.read&#34;&gt;The &lt;code&gt;Read&lt;/code&gt; Mistake&lt;/h3&gt;&#xA;&lt;p&gt;As mentioned earlier, &lt;code&gt;math/rand&lt;/code&gt; is not intended for&#xA;and not suitable for generating cryptographic secrets.&#xA;The &lt;code&gt;crypto/rand&lt;/code&gt; package does that, and its fundamental&#xA;primitive is its &lt;a href=&#34;/pkg/crypto/rand/#Read&#34;&gt;&lt;code&gt;Read&lt;/code&gt; function&lt;/a&gt;&#xA;and &lt;a href=&#34;/pkg/crypto/rand/#Reader&#34;&gt;&lt;code&gt;Reader&lt;/code&gt;&lt;/a&gt; variable.&lt;/p&gt;&#xA;&lt;p&gt;In 2015, we accepted a proposal to make&#xA;&lt;code&gt;rand.Rand&lt;/code&gt; implement &lt;code&gt;io.Reader&lt;/code&gt; as well,&#xA;along with &lt;a href=&#34;/pkg/math/rand/#Read&#34;&gt;adding a top-level &lt;code&gt;Read&lt;/code&gt; function&lt;/a&gt;.&#xA;This seemed reasonable at the time,&#xA;but in retrospect we did not pay enough attention to the&#xA;software engineering aspects of this change.&#xA;Now if you want to read random data, now you have&#xA;two choices: &lt;code&gt;math/rand.Read&lt;/code&gt; and &lt;code&gt;crypto/rand.Read&lt;/code&gt;.&#xA;If the data is going to be used for key material,&#xA;it is very important to use &lt;code&gt;crypto/rand&lt;/code&gt;,&#xA;but now it is possible to use &lt;code&gt;math/rand&lt;/code&gt; instead,&#xA;potentially with disastrous consequences.&lt;/p&gt;&#xA;&lt;p&gt;Tools like &lt;code&gt;goimports&lt;/code&gt; and &lt;code&gt;gopls&lt;/code&gt; have a special case&#xA;to make sure they prefer to use &lt;code&gt;rand.Read&lt;/code&gt; from&#xA;&lt;code&gt;crypto/rand&lt;/code&gt; instead of &lt;code&gt;math/rand&lt;/code&gt;, but that&amp;rsquo;s not a complete fix.&#xA;It would be better to remove &lt;code&gt;Read&lt;/code&gt; entirely.&lt;/p&gt;&#xA;&lt;h2 id=&#34;fix.v1&#34;&gt;Fixing &lt;code&gt;math/rand&lt;/code&gt; directly&lt;/h2&gt;&#xA;&lt;p&gt;Making a new, incompatible major version of a package is never our first choice:&#xA;that new version only benefits programs that switch to it,&#xA;leaving all existing usage of the old major version behind.&#xA;In contrast, fixing a problem in the existing package has much more impact,&#xA;since it fixes all the existing usage.&#xA;We should never create a &lt;code&gt;v2&lt;/code&gt; without doing as much as possible to fix &lt;code&gt;v1&lt;/code&gt;.&#xA;In the case of &lt;code&gt;math/rand&lt;/code&gt;, we were able to partly address&#xA;a few of the problems described above:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Go 1.8 introduced an optional &lt;a href=&#34;/pkg/math/rand/#Uint64&#34;&gt;&lt;code&gt;Source64&lt;/code&gt; interface&lt;/a&gt; with a &lt;code&gt;Uint64&lt;/code&gt; method.&#xA;If a &lt;code&gt;Source&lt;/code&gt; also implements &lt;code&gt;Source64&lt;/code&gt;, then &lt;code&gt;Rand&lt;/code&gt; uses that method&#xA;when appropriate.&#xA;This “extension interface” pattern provides a compatible (if slightly awkward)&#xA;way to revise an interface after the fact.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Go 1.20 automatically seeded the top-level generator and&#xA;deprecated &lt;a href=&#34;/pkg/math/rand/#Seed&#34;&gt;&lt;code&gt;rand.Seed&lt;/code&gt;&lt;/a&gt;.&#xA;Although this may seem like an incompatible change&#xA;given our focus on repeatability of the output stream,&#xA;&lt;a href=&#34;/issue/56319&#34;&gt;we reasoned&lt;/a&gt; that any imported package that called &lt;a href=&#34;/pkg/math/rand/#Int&#34;&gt;&lt;code&gt;rand.Int&lt;/code&gt;&lt;/a&gt;&#xA;at init time or inside any computation would also&#xA;visibly change the output stream, and surely adding or removing&#xA;such a call cannot be considered a breaking change.&#xA;And if that&amp;rsquo;s true, then auto-seeding is no worse,&#xA;and it would eliminate this source of fragility for future programs.&#xA;We also added a &lt;a href=&#34;/doc/godebug&#34;&gt;GODEBUG setting&lt;/a&gt; to opt&#xA;back into the old behavior.&#xA;Then we marked the top-level &lt;code&gt;rand.Seed&lt;/code&gt; as &lt;a href=&#34;/wiki/Deprecated&#34;&gt;deprecated&lt;/a&gt;.&#xA;(Programs that need seeded repeatability can still use&#xA;&lt;code&gt;rand.New(rand.NewSource(seed))&lt;/code&gt; to obtain a local generator&#xA;instead of using the global one.)&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Having eliminated repeatability of the global output stream,&#xA;Go 1.20 was also able to make the global generator scale better&#xA;in programs that don&amp;rsquo;t call &lt;code&gt;rand.Seed&lt;/code&gt;,&#xA;replacing the Go 1 generator with a very cheap per-thread&#xA;&lt;a href=&#34;https://github.com/wangyi-fudan/wyhash&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;wyrand generator&lt;/a&gt;&#xA;already used inside the Go runtime. This removed the global mutex&#xA;and made the top-level functions scale much better.&#xA;Programs that do call &lt;code&gt;rand.Seed&lt;/code&gt; fall back to the&#xA;mutex-protected Go 1 generator.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We were able to adopt Lemire&amp;rsquo;s optimization in the Go runtime,&#xA;and we also used it inside &lt;a href=&#34;/pkg/math/rand/#Shuffle&#34;&gt;&lt;code&gt;rand.Shuffle&lt;/code&gt;&lt;/a&gt;,&#xA;which was implemented after Lemire&amp;rsquo;s paper was published.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Although we couldn&amp;rsquo;t remove &lt;a href=&#34;/pkg/math/rand/#Read&#34;&gt;&lt;code&gt;rand.Read&lt;/code&gt;&lt;/a&gt; entirely,&#xA;Go 1.20 marked it &lt;a href=&#34;/wiki/Deprecated&#34;&gt;deprecated&lt;/a&gt; in favor of&#xA;&lt;code&gt;crypto/rand&lt;/code&gt;.&#xA;We have since heard from people who discovered that they were accidentally&#xA;using &lt;code&gt;math/rand.Read&lt;/code&gt; in cryptographic contexts when their editors&#xA;flagged the use of the deprecated function.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;These fixes are imperfect and incomplete but also real improvements&#xA;that helped all users of the existing &lt;code&gt;math/rand&lt;/code&gt; package.&#xA;For more complete fixes, we needed to turn our attention to &lt;code&gt;math/rand/v2&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;fix.v2&#34;&gt;Fixing the rest in &lt;code&gt;math/rand/v2&lt;/code&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Defining &lt;code&gt;math/rand/v2&lt;/code&gt; took&#xA;significant planning,&#xA;then a &lt;a href=&#34;/issue/60751&#34;&gt;GitHub Discussion&lt;/a&gt;&#xA;and then a &lt;a href=&#34;/issue/61716&#34;&gt;proposal discussion&lt;/a&gt;.&#xA;It is the same&#xA;as &lt;code&gt;math/rand&lt;/code&gt; with the following breaking changes&#xA;addressing the problems outlined above:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We removed the Go 1 generator entirely, replacing it with two new generators,&#xA;&lt;a href=&#34;/pkg/math/rand/v2/#PCG&#34;&gt;PCG&lt;/a&gt; and &lt;a href=&#34;/pkg/math/rand/v2/#ChaCha8&#34;&gt;ChaCha8&lt;/a&gt;.&#xA;The new types are named for their algorithms (avoiding the generic name &lt;code&gt;NewSource&lt;/code&gt;)&#xA;so that if another important algorithm needs to be added, it will fit well into the&#xA;naming scheme.&lt;/p&gt;&#xA;&lt;p&gt;Adopting a suggestion from the proposal discussion, the new types implement the&#xA;&lt;a href=&#34;/pkg/encoding/#BinaryMarshaler&#34;&gt;&lt;code&gt;encoding.BinaryMarshaler&lt;/code&gt;&lt;/a&gt;&#xA;and&#xA;&lt;a href=&#34;/pkg/encoding/#BinaryUnmarshaler&#34;&gt;&lt;code&gt;encoding.BinaryUnmarshaler&lt;/code&gt;&lt;/a&gt;&#xA;interfaces.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We changed the &lt;code&gt;Source&lt;/code&gt; interface, replacing the &lt;code&gt;Int63&lt;/code&gt; method with a &lt;code&gt;Uint64&lt;/code&gt; method&#xA;and deleting the &lt;code&gt;Seed&lt;/code&gt; method. Implementations that support seeding can provide&#xA;their own concrete methods, like &lt;a href=&#34;/pkg/math/rand/v2/#PCG.Seed&#34;&gt;&lt;code&gt;PCG.Seed&lt;/code&gt;&lt;/a&gt; and&#xA;&lt;a href=&#34;/pkg/math/rand/v2/#ChaCha8.Seed&#34;&gt;&lt;code&gt;ChaCha8.Seed&lt;/code&gt;&lt;/a&gt;.&#xA;Note that the two take different seed types, and neither is a single &lt;code&gt;int64&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We removed the top-level &lt;code&gt;Seed&lt;/code&gt; function: the global functions like &lt;code&gt;Int&lt;/code&gt; can only be used&#xA;in auto-seeded form now.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Removing the top-level &lt;code&gt;Seed&lt;/code&gt; also let us hard-code the use of scalable,&#xA;per-thread generators by the top-level methods,&#xA;avoiding a GODEBUG check at each use.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We implemented Lemire&amp;rsquo;s optimization for &lt;code&gt;Intn&lt;/code&gt; and related functions.&#xA;The concrete &lt;code&gt;rand.Rand&lt;/code&gt; API is now locked in to that value stream,&#xA;so we will not be able to take advantage of any optimizations yet to be discovered,&#xA;but at least we are up to date once again.&#xA;We also implemented the &lt;code&gt;Float32&lt;/code&gt; and &lt;code&gt;Float64&lt;/code&gt; optimizations we wanted to use back in Go 1.2.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;During the proposal discussion, a contributor pointed out detectable bias in the&#xA;implementations of &lt;code&gt;ExpFloat64&lt;/code&gt; and &lt;code&gt;NormFloat64&lt;/code&gt;.&#xA;We fixed that bias and locked in the new value streams.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;Perm&lt;/code&gt; and &lt;code&gt;Shuffle&lt;/code&gt; used different shuffling algorithms and produced different value streams,&#xA;because &lt;code&gt;Shuffle&lt;/code&gt; happened second and used a faster algorithm.&#xA;Deleting &lt;code&gt;Perm&lt;/code&gt; entirely would have made migration harder for users.&#xA;Instead we implemented &lt;code&gt;Perm&lt;/code&gt; in terms of &lt;code&gt;Shuffle&lt;/code&gt;, which still lets us&#xA;delete an implementation.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We renamed &lt;code&gt;Int31&lt;/code&gt;, &lt;code&gt;Int63&lt;/code&gt;, &lt;code&gt;Intn&lt;/code&gt;, &lt;code&gt;Int31n&lt;/code&gt;, and &lt;code&gt;Int63n&lt;/code&gt; to&#xA;&lt;code&gt;Int32&lt;/code&gt;, &lt;code&gt;Int64&lt;/code&gt;, &lt;code&gt;IntN&lt;/code&gt;, &lt;code&gt;Int32N&lt;/code&gt;, and &lt;code&gt;Int64N&lt;/code&gt;.&#xA;The 31 and 63 in the names were unnecessarily pedantic&#xA;and confusing, and the capitalized N is more idiomatic for a second&#xA;“word” in the name in Go.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We added &lt;code&gt;Uint&lt;/code&gt;, &lt;code&gt;Uint32&lt;/code&gt;, &lt;code&gt;Uint64&lt;/code&gt;, &lt;code&gt;UintN&lt;/code&gt;, &lt;code&gt;Uint32N&lt;/code&gt;, and &lt;code&gt;Uint64N&lt;/code&gt;&#xA;top-level functions and methods.&#xA;We needed to add &lt;code&gt;Uint64&lt;/code&gt; to provide direct access to the core &lt;code&gt;Source&lt;/code&gt;&#xA;functionality, and it seemed inconsistent not to add the others.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Adopting another suggestion from the proposal discussion,&#xA;we added a new top-level, generic function &lt;code&gt;N&lt;/code&gt; that is like&#xA;&lt;code&gt;Int64N&lt;/code&gt; or &lt;code&gt;Uint64N&lt;/code&gt; but works for any integer type.&#xA;In the old API, to create a random duration of up to 5 seconds,&#xA;it was necessary to write:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;d := time.Duration(rand.Int63n(int64(5*time.Second)))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Using &lt;code&gt;N&lt;/code&gt;, the equivalent code is:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;d := rand.N(5 * time.Second)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;code&gt;N&lt;/code&gt; is only a top-level function; there is no &lt;code&gt;N&lt;/code&gt; method on &lt;code&gt;rand.Rand&lt;/code&gt;&#xA;because there are no generic methods in Go.&#xA;(Generic methods are not likely in the future, either;&#xA;they conflict badly with interfaces, and a complete implementation&#xA;would require either run-time code generation or slow execution.)&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;To ameliorate misuse of &lt;code&gt;math/rand&lt;/code&gt; in cryptographic contexts,&#xA;we made &lt;code&gt;ChaCha8&lt;/code&gt; the default generator used in global functions,&#xA;and we also changed the Go runtime to use it (replacing wyrand).&#xA;Programs are still strongly encouraged to use &lt;code&gt;crypto/rand&lt;/code&gt;&#xA;to generate cryptographic secrets,&#xA;but accidentally using &lt;code&gt;math/rand/v2&lt;/code&gt; is not as catastrophic&#xA;as using &lt;code&gt;math/rand&lt;/code&gt; would be.&#xA;Even in &lt;code&gt;math/rand&lt;/code&gt;, the global functions now use the &lt;code&gt;ChaCha8&lt;/code&gt; generator when not explicitly seeded.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;principles&#34;&gt;Principles for evolving the Go standard library&lt;/h2&gt;&#xA;&lt;p&gt;As mentioned at the start this post, one of the goals for this work&#xA;was to establish principles and a pattern for how we approach all&#xA;v2 packages in the standard library.&#xA;There will not be a glut of v2 packages&#xA;in the next few Go releases.&#xA;Instead, we will handle one package&#xA;at a time, making sure we set a quality bar that will last for another decade.&#xA;Many packages will not need a v2 at all.&#xA;But for those that do, our approach boils down to three principles.&lt;/p&gt;&#xA;&lt;p&gt;First, a new, incompatible version of a package will use&#xA;&lt;code&gt;that/package/v2&lt;/code&gt; as its import path,&#xA;following&#xA;&lt;a href=&#34;https://research.swtch.com/vgo-import&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;semantic import versioning&lt;/a&gt;&#xA;just like a v2 module outside the standard library would.&#xA;This allows uses of the original package and the v2 package&#xA;to coexist in a single program,&#xA;which is critical for a&#xA;&lt;a href=&#34;/talks/2016/refactor.article&#34;&gt;gradual conversion&lt;/a&gt; to the new API.&lt;/p&gt;&#xA;&lt;p&gt;Second, all changes must be rooted in&#xA;respect for existing usage and users:&#xA;we must not introduce needless churn,&#xA;whether in the form of unnecessary changes to an existing package or&#xA;an entirely new package that must be learned instead.&#xA;In practice, that means we take the existing package&#xA;as the starting point&#xA;and only make changes that are well motivated&#xA;and provide a value that justifies the cost to users of updating.&lt;/p&gt;&#xA;&lt;p&gt;Third, the v2 package must not leave v1 users behind.&#xA;Ideally, the v2 package should be able to do everything the v1 package&#xA;could do,&#xA;and when v2 is released, the v1 package should be rewritten&#xA;to be a thin wrapper around v2.&#xA;This would ensure that existing uses of v1 continue to benefit&#xA;from bug fixes and performance optimizations in v2.&#xA;Of course, given that v2 is introducing breaking changes,&#xA;this is not always possible, but it is always something to consider carefully.&#xA;For &lt;code&gt;math/rand/v2&lt;/code&gt;, we arranged for the auto-seeded v1 functions to&#xA;call the v2 generator, but we were unable to share other code&#xA;due to the repeatability violations.&#xA;Ultimately &lt;code&gt;math/rand&lt;/code&gt; is not a lot of code and does not require&#xA;regular maintenance, so the duplication is manageable.&#xA;In other contexts, more work to avoid duplication could be worthwhile.&#xA;For example, in the&#xA;&lt;a href=&#34;/issue/63397&#34;&gt;encoding/json/v2 design (still in progress)&lt;/a&gt;,&#xA;although the default semantics and the API are changed,&#xA;the package provides configuration knobs that&#xA;make it possible to implement the v1 API.&#xA;When we eventually ship &lt;code&gt;encoding/json/v2&lt;/code&gt;,&#xA;&lt;code&gt;encoding/json&lt;/code&gt; (v1) will become a thin wrapper around it,&#xA;ensuring that users who don&amp;rsquo;t migrate from v1 still&#xA;benefit from optimizations and security fixes in v2.&lt;/p&gt;&#xA;&lt;p&gt;A &lt;a href=&#34;/blog/chacha8rand&#34;&gt;follow-up blog post&lt;/a&gt; presents the &lt;code&gt;ChaCha8&lt;/code&gt; generator in more detail.&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;Article prevnext&#34;&gt;&#xA;    &#xA;    &#xA;      &#xA;    &#xA;      &#xA;        &lt;p&gt;&#xA;        &#xA;          &#xA;            &lt;b&gt;Next article: &lt;/b&gt;&lt;a href=&#34;/blog/chacha8rand&#34;&gt;Secure Randomness in Go 1.22&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &#xA;          &#xA;            &lt;b&gt;Previous article: &lt;/b&gt;&lt;a href=&#34;/blog/survey2024-h1-results&#34;&gt;Go Developer Survey 2024 H1 Results&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &lt;b&gt;&lt;a href=&#34;/blog/all&#34;&gt;Blog Index&lt;/a&gt;&lt;/b&gt;&#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;    &lt;/div&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script src=&#34;/js/jquery.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/playground.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/play.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/godocs.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;</content></entry><entry><title>Go Developer Survey 2024 H1 Results</title><id>tag:blog.golang.org,2013:blog.golang.org/survey2024-h1-results</id><link rel="alternate" href="https://go.dev/blog/survey2024-h1-results"></link><published>2024-04-09T00:00:00+00:00</published><updated>2024-04-09T00:00:00+00:00</updated><author><name></name></author><summary type="html">What we learned from our 2024 H1 developer survey</summary><content type="html">&#xA;&lt;div id=&#34;blog&#34;&gt;&lt;div id=&#34;content&#34;&gt;&#xA;  &lt;div id=&#34;content&#34;&gt;&#xA;&#xA;    &lt;div class=&#34;Article&#34; data-slug=&#34;/blog/survey2024-h1-results&#34;&gt;&#xA;    &#xA;    &lt;h1 class=&#34;small&#34;&gt;&lt;a href=&#34;/blog/&#34;&gt;The Go Blog&lt;/a&gt;&lt;/h1&gt;&#xA;    &#xA;&#xA;    &lt;h1&gt;Go Developer Survey 2024 H1 Results&lt;/h1&gt;&#xA;      &#xA;      &lt;p class=&#34;author&#34;&gt;&#xA;      Alice Merrick and Todd Kulesza&lt;br&gt;&#xA;      9 April 2024&#xA;      &lt;/p&gt;&#xA;      &#xA;      &lt;style type=&#34;text/css&#34; scoped&gt;&#xA;  .chart {&#xA;    margin-left: 1.5rem;&#xA;    margin-right: 1.5rem;&#xA;    width: 800px;&#xA;  }&#xA;  blockquote p {&#xA;    color: var(--color-text-subtle) !important;&#xA;  }&#xA;&#xA;  .quote_source {&#xA;    font-style: italic;&#xA;  }&#xA;&#xA;  @media (prefers-color-scheme: dark) {&#xA;    .chart {&#xA;      border-radius: 8px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;&#xA;&lt;p&gt;This post shares the results of our most recent Go Developer Survey, conducted&#xA;in January and February 2024. Along with capturing sentiments and challenges&#xA;around using Go and Go tooling, our primary focus areas for this survey were&#xA;about how developers are starting to use Go (or other languages) for&#xA;AI-related use cases, and particular challenges for those who are learning Go&#xA;or looking to expand their Go skill set.&lt;/p&gt;&#xA;&lt;p&gt;We recruited participants from the Go blog and through randomized prompts in&#xA;the VS Code Go plug-in. This year, with the help of&#xA;&lt;a href=&#34;https://jetbrains.com&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;JetBrains&lt;/a&gt;, we also included a randomized survey prompt in the&#xA;&lt;a href=&#34;https://jetbrains.com/go/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;GoLand IDE&lt;/a&gt;, allowing us to recruit a more&#xA;representative sample of Go developers. We received a total of 6,224&#xA;responses! A huge thank you to all those who contributed to making this&#xA;possible.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tldr&#34;&gt;Highlights&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Developer sentiment remains high, with 93% of respondents expressing&#xA;satisfaction with Go over the past year.&lt;/li&gt;&#xA;&lt;li&gt;A majority of respondents (80%) said they trust the Go team to &amp;ldquo;do what&amp;rsquo;s&#xA;best&amp;rdquo; for developers like themselves when maintaining and evolving the&#xA;language.&lt;/li&gt;&#xA;&lt;li&gt;Among survey respondents who build AI-powered applications and services,&#xA;there is a shared sense that Go is a strong platform for running these types&#xA;of applications in production. For example, a majority of respondents&#xA;working with AI-powered applications already use Go or would like to migrate&#xA;to Go for their AI-powered workloads, and the most serious challenges&#xA;developers encounter are related to the library and documentation ecosystems&#xA;rather than the core language and runtime. That said, the most commonly&#xA;documented paths for getting started are currently Python-centric, resulting&#xA;in many organizations starting AI-powered work in Python before moving to a&#xA;more production-ready language.&lt;/li&gt;&#xA;&lt;li&gt;The most common kinds of AI-powered services respondents are building&#xA;include summarization tools, text generation tools, and chatbots. Responses&#xA;suggest that many of these use cases are internal-facing, such as chatbots&#xA;trained upon an organization&amp;rsquo;s internal documentation and intended to answer&#xA;employee questions. We hypothesize that organizations are intentionally&#xA;starting with internal use cases to develop in-house expertise with LLMs&#xA;while avoiding potential public embarrassment when AI-powered agents behave&#xA;unexpectedly.&lt;/li&gt;&#xA;&lt;li&gt;Lack of time or opportunities was the most commonly cited challenge for&#xA;respondents to reaching their Go-related learning goals, suggesting that&#xA;language learning is difficult to prioritize without a specific goal or&#xA;business case in mind. The next most common challenge was in learning new&#xA;best practices, concepts, and idioms that are particular to Go when coming&#xA;from other language ecosystems.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;contents&#34;&gt;Contents&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#sentiment&#34;&gt;Developer sentiment&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#devenv&#34;&gt;Developer environments&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#priorities&#34;&gt;Resource and performance priorities&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#mlai&#34;&gt;Understanding AI use cases for Go&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#learn&#34;&gt;Learning challenges&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#demographics&#34;&gt;Demographics&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#firmographics&#34;&gt;Firmographics&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#methodology&#34;&gt;Methodology&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#closing&#34;&gt;Closing&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;sentiment&#34;&gt;Developer sentiment&lt;/h2&gt;&#xA;&lt;p&gt;Overall satisfaction remains high in the survey with 93% of respondents saying&#xA;they were somewhat or very satisfied with Go during the last year. This isn&amp;rsquo;t&#xA;surprising, considering our audience is those who have voluntarily taken our&#xA;survey. But even among those who were randomly sampled from both VS Code and&#xA;GoLand, we still see comparable rates of satisfaction (92%). Although the&#xA;exact percentages fluctuate slightly from survey to survey, we do not see any&#xA;statistically significant differences from &lt;a href=&#34;/blog/survey2023-h2-results&#34;&gt;2023&#xA;H2&lt;/a&gt;, when the satisfaction rate was&#xA;90%.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/csat.svg&#34; alt=&#34;Chart of developer satisfaction with Go&#34;&#xA;class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;trust&#34;&gt;Trust&lt;/h3&gt;&#xA;&lt;p&gt;This year we introduced a new metric for measuring developer trust. This was&#xA;an experimental question and its wording may change over time as we learn more&#xA;about how respondents interpreted it. Because this is the first time we asked&#xA;this question, we don&amp;rsquo;t have previous years to give us context for our&#xA;results. We found that 80% of respondents somewhat or strongly agree that they&#xA;trust the Go team to do what&amp;rsquo;s best for users like them. Respondents with 5 or&#xA;more years of experience with Go tended to agree more (83%) than those with&#xA;less than 2 years of experience (77%). This could reflect &lt;a href=&#34;https://en.wikipedia.org/wiki/Survivorship_bias&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;survivorship&#xA;bias&lt;/a&gt; in that those who trust&#xA;the Go team more are more likely to continue using Go, or may reflect how&#xA;trust is calibrated over time.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/trust_go.svg&#34; alt=&#34;Chart of developer trust with the Go&#xA;team&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;community&#34;&gt;Community satisfaction&lt;/h3&gt;&#xA;&lt;p&gt;In the last year, almost a third of respondents (32%) said they participated&#xA;in the Go developer community either online or at in-person events. More&#xA;experienced Go developers were more likely to have participated in a community&#xA;event and were more satisfied with community events overall. Although we can&amp;rsquo;t&#xA;draw causal conclusions from this data, we did see a positive correlation&#xA;between community satisfaction and overall satisfaction with Go. It could be&#xA;that participating in the Go community increases satisfaction through&#xA;increased social interaction or technical support. In general, we also found&#xA;that respondents with less experience were less likely to have participated in&#xA;events in the last year. This may mean they haven&amp;rsquo;t discovered events or found&#xA;opportunities yet to be involved.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/community_events.svg&#34; alt=&#34;Chart of participation in&#xA;community events&#34; class=&#34;chart&#34; /&gt; &lt;img src=&#34;survey2024h1/community_sat.svg&#34;&#xA;alt=&#34;Chart of community satisfaction&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;biggestchallenge&#34;&gt;Biggest challenges&lt;/h3&gt;&#xA;&lt;p&gt;For several years, this survey has asked participants about their biggest&#xA;challenge when using Go. This has always been in the form of an open text box&#xA;and has elicited a wide variety of responses. In this cycle we introduced a&#xA;closed form of the question, where we provided the most common write-in&#xA;responses from prior years. Respondents were randomly shown either the open or&#xA;closed forms of the question. The closed form helps us validate how we&amp;rsquo;ve&#xA;historically interpreted these responses, while also increasing the number of&#xA;Go developers we hear from: this year participants who saw the closed form&#xA;were 2.5x more likely to answer than those who saw the open form. This higher&#xA;number of responses narrows our margin of error and increases our confidence&#xA;when interpreting survey results.&lt;/p&gt;&#xA;&lt;p&gt;In the closed-form, only 8% of respondents selected &amp;ldquo;Other&amp;rdquo;, which suggests we&#xA;captured the majority of common challenges with our response choices.&#xA;Interestingly, 13% of respondents said they don&amp;rsquo;t face any challenges using&#xA;Go. In the open text version of this question, only 2% of respondents gave&#xA;this response. The top responses in the closed-form were learning how to write&#xA;Go effectively (15%) and the verbosity of error handling (13%). This matches&#xA;what we saw in the open-text form, where 11% of responses mentioned learning&#xA;Go, learning best practices, or issues with documentation as their biggest&#xA;challenge, and another 11% mentioned error handling.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/biggest_challenge_closed.svg&#34; alt=&#34;Chart of closed form&#xA;biggest challenges using Go&#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2024h1/text_biggest_challenge.svg&#34; alt=&#34;Chart of open text biggest&#xA;challenges using Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Respondents who saw the closed form of the question also received a follow-up&#xA;open-text question to give them an opportunity to tell us more about their&#xA;biggest challenge in case they had wanted to provide more nuanced answers,&#xA;additional challenges, or anything else they felt was important.The most&#xA;common response mentioned Go&amp;rsquo;s type system, and often asked specifically for&#xA;enums, option types, or sum types in Go. Often we did not get much context for&#xA;these requests, but we suspect this is due to some recent proposals and&#xA;community discussions related to enums, an increase in folks coming from other&#xA;language ecosystems where these features are common, or the expectation that&#xA;these features will reduce writing boilerplate code. One of the more&#xA;comprehensive comments related to the type system explained as follows:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;These aren&amp;rsquo;t big challenges, but more conveniences I miss in the language.&#xA;There&amp;rsquo;s ways around all of them, but it would be nice not to have to think&#xA;about it.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Sum types/closed enums can be emulated but its a lot of faff. It&amp;rsquo;s a very&#xA;handy feature to have when interacting with APIs that only have a limited&#xA;set of values for a particular element/field in a response and a value&#xA;outside of it is an error. It helps with validation and catching issues at&#xA;the point of entry and can often directly be generated from API&#xA;specifications like JSON Schema, OpenAPI or heaven forbid XML Schema&#xA;Definitions.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t mind the error checking verbosity at all, but the nil-checking with&#xA;pointers gets tedious especially when [I] need to drill into a deeply nested&#xA;struct of pointer fields. Some form of Optional/Result type or an ability to&#xA;chase through a chain of pointers and simply get a nil back instead of&#xA;triggering a runtime panic would be appreciated.&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/text_biggest_challenge_anything.svg&#34; alt=&#34;Chart of&#xA;anything else related to biggest challenges using Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;devenv&#34;&gt;Developer environments&lt;/h2&gt;&#xA;&lt;p&gt;As in previous years, most survey respondents develop with Go on Linux (61%)&#xA;and macOS (58%) systems. Although the numbers haven&amp;rsquo;t changed much from year&#xA;to year, we did see some interesting differences in our self-selected sample.&#xA;The randomly sampled groups from JetBrains and VS Code were more likely (31%&#xA;and 33%, respectively) to develop on Windows than the self-selected group&#xA;(19%). We don&amp;rsquo;t know exactly why the self-selected group is so different, but&#xA;we hypothesize that, because they likely encountered the survey from reading&#xA;the Go Blog, these respondents are some of the most engaged and experienced&#xA;developers in the community. Their operating system preferences might be&#xA;reflective of historical priorities of the core development team who typically&#xA;developed on Linux and macOS. Thankfully we have the random samples from&#xA;JetBrains and VS Code to provide a more representative view of developer&#xA;preferences.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/os_dev.svg&#34; alt=&#34;Chart of operating systems respondents&#xA;use when developing Go software&#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2024h1/os_dev_src.svg&#34; alt=&#34;Chart of operating systems respondents&#xA;use when developing Go software, split by difference sample sources&#34;&#xA;class=&#34;chart&#34; /&gt; &lt;img src=&#34;survey2024h1/os_dev_exp.svg&#34; alt=&#34;Chart of&#xA;operating systems respondents use when developing Go software, split by&#xA;duration of experience&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;As a followup for the 17% of respondents who develop on WSL, we asked which&#xA;version they&amp;rsquo;re using. 93% of respondents who develop on WSL are using version&#xA;2, so going forward, &lt;a href=&#34;/issue/63503&#34;&gt;the Go team at Microsoft has decided to focus their&#xA;efforts on WSL2.&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/wsl_version.svg&#34; alt=&#34;Chart of WSL versions usage&#34;&#xA;class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Given that two of our sample populations were recruited from within VS Code or&#xA;GoLand, they are strongly biased towards preferring those editors. To avoid&#xA;skewing the results, we show the data here from the self-selected group only.&#xA;Similar to previous years, the most common code editors among Go Developer&#xA;Survey respondents continue to be &lt;a href=&#34;https://code.visualstudio.com/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;VS Code&lt;/a&gt;&#xA;(43%) and &lt;a href=&#34;https://www.jetbrains.com/go/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;GoLand&lt;/a&gt; (33%). We don&amp;rsquo;t see any&#xA;statistically significant differences from mid-2023, (44% and 31%,&#xA;respectively).&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/editor.svg&#34; alt=&#34;Chart of code editors respondents&#xA;prefer to use with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;With the prevalence of Go for cloud development and containerized workloads,&#xA;it&amp;rsquo;s no surprise that Go developers primarily deploy to Linux environments&#xA;(93%). We didn&amp;rsquo;t see any significant changes from last year.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/os_deploy.svg&#34; alt=&#34;Chart of platforms respondents&#xA;deploy Go software to&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Go is a popular language for modern cloud-based development, so we typically&#xA;include survey questions to help us understand which cloud platforms Go&#xA;developers are using and how satisfied they are with the three most popular&#xA;platforms: Amazon Web Services (AWS), Microsoft Azure, and Google Cloud. This&#xA;section was only shown to respondents who said they use Go for their primary&#xA;job, about 76% of total respondents. 98% of those who saw this question work&#xA;on Go software that integrates with cloud services. Over half of respondents&#xA;used AWS (52%), while 27% used GCP for their Go development and deployments.&#xA;For both AWS and Google Cloud, we don&amp;rsquo;t see any differences between small or&#xA;large companies in their likelihood to use either provider. Microsoft Azure is&#xA;the only cloud provider that is significantly more likely to be used in large&#xA;organizations (companies with &amp;gt; 1,000 employees) than smaller shops. We didn&amp;rsquo;t&#xA;see any significant differences in usage based on the size of the organization&#xA;for any other cloud providers.&lt;/p&gt;&#xA;&lt;p&gt;The rates of satisfaction for using Go with AWS and Google Cloud were both&#xA;77%. Historically these rates have been about the same. As in previous years,&#xA;the satisfaction rate for Microsoft Azure was lower (57%).&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/cloud_platform.svg&#34; alt=&#34;Chart of cloud platforms&#xA;respondents&#34; class=&#34;chart&#34; /&gt; &lt;img src=&#34;survey2024h1/cloud_sat_aws.svg&#34;&#xA;alt=&#34;Chart of satisfaction with Go on AWS in the last year&#34; class=&#34;chart&#34; /&gt;&#xA;&lt;img src=&#34;survey2024h1/cloud_sat_gcp.svg&#34; alt=&#34;Chart of satisfaction with&#xA;using Go on Google Cloud in the last year&#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2024h1/cloud_sat_azure.svg&#34; alt=&#34;Chart of satisfaction with using&#xA;Go on Microsoft Azure in the last year&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;priorities&#34;&gt;Resource and Security Priorities&lt;/h2&gt;&#xA;&lt;p&gt;To help prioritize the Go team&amp;rsquo;s work, we wanted to understand the top&#xA;resource cost and security concerns for teams using Go. About half of&#xA;respondents using Go at work reported having at least one resource cost&#xA;concern in the last year (52%). The engineering costs of writing and maintaining Go&#xA;services was more common (28%) than concern for the costs of running Go&#xA;services (10%) or both about equally (12%). We didn&amp;rsquo;t see any significant&#xA;differences in resource concerns between small and large organizations. To&#xA;address concerns about resource costs, the Go team is continuing to optimize&#xA;Go and enhance profile-guided optimization (PGO).&lt;/p&gt;&#xA;&lt;img src=&#34;survey2024h1/cost_concern.svg&#34; alt=&#34;Chart of cost concerns respondents have had related to their Go usage in the last year&#34; class=&#34;chart&#34; /&gt;&#xA;&lt;p&gt;As for security priorities, we asked respondents to tell us up to three of&#xA;their top concerns. Of those who did have security concerns, overall, the top&#xA;concern was insecure coding practices (42%), followed by system&#xA;misconfiguration (29%). Our main takeaway is that respondents are especially&#xA;interested in tooling to help find and fix potential security issues while&#xA;they&amp;rsquo;re writing code. This aligns with what we&amp;rsquo;ve learned from prior research&#xA;into how developers find and address security vulnerabilities.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/security_concern.svg&#34; alt=&#34;Chart of cost concerns&#xA;respondents have had related Go usage in the last year&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;perf&#34;&gt;Performance Tooling&lt;/h3&gt;&#xA;&lt;p&gt;Our goals for this section were to measure how respondents perceive the ease&#xA;or difficulty of diagnosing performance issues and determine whether this task&#xA;is more or less difficult depending on their editor or IDE usage.&#xA;Specifically, we wanted to know if it&amp;rsquo;s more difficult to diagnose performance&#xA;issues from the command line, and if we should invest in improving the&#xA;integration of performance diagnostic tooling within VS Code to make this task&#xA;easier. In our analyses, we show comparisons between respondents who prefer VS&#xA;Code or GoLand to highlight what we learned about the experience of using VS&#xA;Code compared to another common editor.&lt;/p&gt;&#xA;&lt;p&gt;We first asked a general question about different kinds of tools and&#xA;techniques respondents use with Go to have some points of comparison. We found&#xA;that only 40% of respondents use tools to improve code performance or&#xA;efficiency. We didn&amp;rsquo;t see any significant differences based on editor or IDE&#xA;preference, that is, VS Code users and GoLand users were about equally likely&#xA;to use tools to improve code performance or efficiency.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/dev_techniques.svg&#34; alt=&#34;Chart of different techniques&#xA;used for security, quality and performance&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Most respondents (73%) told us that identifying and addressing performance&#xA;issues is at least moderately important. Again, we didn&amp;rsquo;t see any significant&#xA;differences here between GoLand and VS Code users in how important they found&#xA;diagnosing performance issues.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/perf_importance.svg&#34; alt=&#34;Chart of the importance of&#xA;identifying and addressing performance issues &#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Overall, respondents did not find diagnosing performance issues easy, with 30%&#xA;reporting it was somewhat or very difficult and 46% saying it was neither easy&#xA;nor difficult. Contrary to our hypothesis, VS Code users were not more likely&#xA;to report challenges when diagnosing performance issues vs. other respondents.&#xA;Those using their command line for diagnosing performance issues, regardless&#xA;of their preferred editor, also did not report this task as more challenging&#xA;than those using their IDE. Years of experience was the only significant&#xA;factor we observed, where less experienced Go developers found it overall more&#xA;difficult to diagnose performance issues than more experienced Go developers.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/perf_easiness.svg&#34; alt=&#34;Chart of how easy or difficult&#xA;respondents found diagnosing performance issues &#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2024h1/perf_easiness_exp.svg&#34; alt=&#34;Chart of how easy or difficult&#xA;respondents found diagnosing performance issues split by duration of&#xA;experience&#34; class=&#34;chart&#34; /&gt; &lt;img src=&#34;survey2024h1/perf_easiness_where.svg&#34;&#xA;alt=&#34;Chart of how easy or difficult respondents found diagnosing performance&#xA;issues split by where they use performance diagnostic tools &#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;To answer our original question, most developers found it difficult to&#xA;diagnose performance issues in Go, regardless of their preferred editor or&#xA;tooling. This was especially true for developers with less than two years of&#xA;experience in Go.&lt;/p&gt;&#xA;&lt;p&gt;We also included a follow-up for respondents who rated diagnosing performance&#xA;issues as at least slightly important to understand which issues were most&#xA;important to them. Latency, total memory, and total CPU were the top concerns.&#xA;There could be several explanations to the significance of these areas. First,&#xA;they are measurable and easily convertible into business costs. Secondly,&#xA;total memory and CPU usage represent physical constraints that necessitate&#xA;hardware upgrades or software optimizations for improvement. Moreover,&#xA;latency, total memory, and total CPU are more manageable by developers and can&#xA;impact even straightforward services. In contrast, GC performance and memory&#xA;allocation may only be relevant in rare cases or for exceptionally heavy&#xA;workloads. Additionally, latency stands out as the most user-visible metric,&#xA;as high latency results in slow services and dissatisfied users.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/perf_concerns.svg&#34; alt=&#34;Chart of which performance&#xA;issues are the highest concern to respondents&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;mlai&#34;&gt;Understanding AI use cases for Go&lt;/h2&gt;&#xA;&lt;p&gt;Our &lt;a href=&#34;/blog/survey2023-h2-results#mlai&#34;&gt;previous survey&lt;/a&gt; asked Go&#xA;developers about their early experiences with generative AI systems. To go a&#xA;bit deeper this cycle, we asked several AI-related questions to understand how&#xA;respondents are building AI-powered (more specifically, LLM-powered) services.&#xA;We found that half of survey respondents (50%) work at organizations that are&#xA;building or exploring AI-powered services. Of these, just over half (56%) said&#xA;they were involved with adding AI capabilities to their organization&amp;rsquo;s&#xA;services. Our remaining AI-related questions were only shown to this slice of&#xA;respondents.&lt;/p&gt;&#xA;&lt;p&gt;Please be cautious about generalizing these participant responses to the&#xA;overall population of Go developers. Because only about ¼ of survey&#xA;respondents are working with AI-powered services, we suggest using this data&#xA;to understand the early adopters in this space, with the caveat that early&#xA;adopters tend to be a bit different than the majority of people who will&#xA;eventually adopt a technology. As an example, we expect that this audience is&#xA;experimenting with more models and SDKs than may be the case a year or two&#xA;from now, and encountering more challenges related to integrating those&#xA;services into their existing code base.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/ai_org.svg&#34; alt=&#34;Chart of respondents whose org is&#xA;currently building or exploring ML/AI based services&#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2024h1/ai_involved.svg&#34; alt=&#34;Chart of respondents who are currently&#xA;involved in their orgs AI based development&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Among the audience of Go developers working professionally with generative AI&#xA;(GenAI) systems, a solid majority (81%) reported using OpenAI&amp;rsquo;s ChatGPT or&#xA;DALL-E models. A collection of open-source models also saw high adoption, with&#xA;a majority of respondents (53%) using at least one of Llama, Mistral, or&#xA;another OSS model. We see some early evidence that larger organizations&#xA;(1,000+ employees) are a bit less likely to be using OpenAI models (74% vs.&#xA;83%) and a bit more likely to be using other proprietary models (22% vs. 11%).&#xA;We do not, however, see any evidence of differences in adoption of OSS models&#xA;based on organization size–both smaller companies and larger enterprises show&#xA;small majorities adopting OSS models (51% and 53%, respectively). Overall we&#xA;found that a plurality of respondents prefer to use open-source models (47%)&#xA;with only 19% preferring proprietary models; 37% said they had no preference.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/generative_models.svg&#34; alt=&#34;Chart of which generative&#xA;AI models respondents&#39; orgs are using&#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2024h1/ai_libs.svg&#34; alt=&#34;Chart of which AI related services and&#xA;libraries respondents&#39; orgs are using&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;The most common kinds of services respondents are building include&#xA;summarization tools (56%), text generation tools (55%), and chatbots (46%).&#xA;Open-text responses suggested that many of these use cases are&#xA;internal-facing, such as chat bots trained upon an organization&amp;rsquo;s internal&#xA;documentation and intended to answer employee questions. Respondents raised&#xA;several concerns about external-facing AI features, most notably due to&#xA;reliability (e.g., do slight changes in my question lead to very different&#xA;results?) and accuracy (e.g., are the results trustworthy?) issues. An&#xA;interesting theme running through these responses was a sense of tension&#xA;between the risk of not adopting AI tooling at all (and thereby losing a&#xA;potential competitive advantage should generative AI become necessary in the&#xA;future), balanced against the risk of negative publicity or violating&#xA;regulations/laws by using untested AI in high-criticality customer-facing&#xA;domains.&lt;/p&gt;&#xA;&lt;p&gt;We found evidence that Go is already being used in the GenAI space, and there&#xA;appears to be an appetite for more. Roughly ⅓ of respondents who were building&#xA;AI-powered features told us they were already using Go for a variety of GenAI&#xA;tasks, including prototyping new features and integrating services with LLMs.&#xA;These proportions tick up slightly for two areas where we believe Go is a&#xA;particularly well-suited tool: data pipelines for ML/AI systems (37%) and&#xA;hosting API endpoints for ML/AI models (41%). In addition to these (likely&#xA;early) adopters, we found that about ¼ of respondents &lt;em&gt;want&lt;/em&gt; to use Go for&#xA;these types of uses, but are currently blocked by something. We&amp;rsquo;ll return to&#xA;these blockers shortly, after exploring why respondents wanted to use Go for&#xA;these tasks in the first place.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/ai_apps.svg&#34; alt=&#34;Chart of the kinds of Generative AI&#xA;apps respondents work on&#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2024h1/ai_uses_interest.svg&#34; alt=&#34;Chart of the kinds of AI apps&#xA;respondents&#39; orgs are currently working on or considering&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;reasons-for-using-go-with-generative-ai-systems&#34;&gt;Reasons for using Go with generative AI systems&lt;/h3&gt;&#xA;&lt;p&gt;To help us understand what benefits developers hope to derive from using Go in&#xA;their AI/ML services, we asked developers why they feel Go is a good choice&#xA;for this domain. A clear majority (61%) of respondents mentioned one or more&#xA;of Go&amp;rsquo;s core principles or features, such as simplicity, runtime safety,&#xA;concurrency, or single-binary deployments. One third of respondents cited&#xA;existing familiarity with Go, including a desire to avoid introducing new&#xA;languages if they can avoid it. Rounding out the most common responses were&#xA;various challenges with Python (particularly for running production services)&#xA;at 14%.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;I think that the robustness, simplicity, performance and native binaries&#xA;that the language offers make it a far stronger choice for AI workloads.&amp;rdquo;&#xA;&lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Open-source Go developer at a large&#xA;organization with up to 1 year of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;We want to keep our tech stack as homogenous as possible across the&#xA;organization to make it easier for everybody to develop on all areas. Since&#xA;we are already writing all our backends in Go, it is of interest to us to be&#xA;able to write ML model deployments in Go and avoid having to rewrite parts&#xA;of the stack for logging, monitoring, etc&amp;hellip; in a separate language [like]&#xA;Python.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer at a&#xA;mid-sized organization with 5 – 7 years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Go is better for us at running API servers and background tasks on worker&#xA;pools. Go&amp;rsquo;s lower resource usage has allowed us to grow without using more&#xA;resources. And we have found that Go projects are easier to maintain over&#xA;time both in code changes and when updating dependencies. We run the models&#xA;as a separate service written in Python and interact with them in Go.&amp;rdquo;&#xA;&lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer at a large&#xA;organization with 5 – 7 years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;It appears that among Go developers who are interested in ML/AI, there is a&#xA;shared sense that 1) Go is inherently a good language for this domain (for the&#xA;reasons articulated above), and 2) there is reluctance to introduce a new&#xA;language once organizations have already invested in Go (this point reasonably&#xA;generalizes to any language). Some respondents also expressed frustration with&#xA;Python for reasons such as type safety, code quality, and challenging&#xA;deployments.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/text_ml_interest.svg&#34; alt=&#34;Chart of respondents&#39;&#xA;reasons for why Go is a good choice for their AI related use case&#34;&#xA;class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;challenges-when-using-go-with-genai-systems&#34;&gt;Challenges when using Go with GenAI systems&lt;/h3&gt;&#xA;&lt;p&gt;Respondents were largely unified on what currently prevents them from using Go&#xA;with AI-powered services: the ecosystem is centered around Python, their&#xA;favorite libraries/frameworks are all in Python, getting started documentation&#xA;assumes Python familiarity, and the data scientists or researchers exploring&#xA;these models are already familiar with Python.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Python just seems to have all the libraries. PyTorch for example is widely&#xA;used to run models. If there were frameworks in Go to run these models, we&amp;rsquo;d&#xA;much rather be doing that.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go&#xA;developer at a large organization with 2 – 4 years of experience&lt;/space&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Python tools are substantially more mature and usable out of the box,&#xA;making them a significantly lower cost to implement.&amp;rdquo;&#xA;&lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer at a small&#xA;organization with 2 – 4 years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;[The] Go world is missing many AI libraries. If I have a LLM PyTorch model,&#xA;I can&amp;rsquo;t even serve it (or I&amp;rsquo;m unaware how to do it). With Python it&amp;rsquo;s&#xA;basically a few lines of code.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional&#xA;Go developer at a small organization with up to 1 year of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;These findings triangulate well with our observation above that Go developers&#xA;believe Go &lt;em&gt;should&lt;/em&gt; be a great language for building production-ready AI&#xA;services: only 3% of respondents said that something specific to Go was&#xA;blocking their path forward, and only 2% cited specific interoperability&#xA;challenges with Python. In other words, most blockers developers face could be&#xA;resolved in the module and documentation ecosystem, rather than necessitating&#xA;core language or runtime changes.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/text_ml_blockers.svg&#34; alt=&#34;Chart of what is blocking&#xA;respondents from using Go with their AI powered apps&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;We also asked survey participants whether they were already working with&#xA;Python for GenAI, and if so, whether they&amp;rsquo;d prefer to use Go. Respondents who&#xA;said they&amp;rsquo;d prefer to use Go rather than Python also received a follow-up&#xA;about what would enable them to use Go with GenAI systems.&lt;/p&gt;&#xA;&lt;p&gt;A solid majority (62%) of respondents reported already using Python to&#xA;integrate with generative AI models; of this group, 57% would rather use Go&#xA;instead. Given that our survey audience are all Go developers, we should&#xA;expect this to be an approximate upper bound on the proportion of overall&#xA;developers who are interested in moving from Python to Go for GenAI tasks,&#xA;given the state of each ecosystem today.&lt;/p&gt;&#xA;&lt;p&gt;Of the respondents who are already using Python but would prefer to use Go,&#xA;the vast majority (92%) said that the availability of Go equivalents for&#xA;Python libraries would enable them to integrate Go with GenAI systems.&#xA;However, we should be cautious when interpreting this result; the open-text&#xA;responses and a separate set of contextual interviews with developers working&#xA;on GenAI services describe a Python-centric ecosystem around GenAI; it&amp;rsquo;s not&#xA;only that Go lacks many libraries when compared with the Python ecosystem, but&#xA;also that the perceived level of investment into Go libraries is lower,&#xA;documentation and examples are predominantly in Python, and the network of&#xA;experts working in this area are already comfortable with Python.&#xA;Experimenting and building proofs-of-concept in Python is almost certain to&#xA;continue, and the lack of Go variants of Python libraries (for example,&#xA;&lt;a href=&#34;https://pandas.pydata.org/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;pandas&lt;/a&gt;) is only the first barrier developers&#xA;would encounter when trying to port from Python to Go. Libraries and SDKs are&#xA;necessary, but unlikely by themselves to be sufficient, to build a robust Go&#xA;ecosystem for production ML/AI applications.&lt;/p&gt;&#xA;&lt;p&gt;Further, contextual interviews with Go developers building AI-powered services&#xA;suggest that &lt;em&gt;calling&lt;/em&gt; APIs from Go is not a major issue, particularly with&#xA;hosted models such as &lt;a href=&#34;https://openai.com/gpt-4&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;GPT-4&lt;/a&gt; or&#xA;&lt;a href=&#34;https://gemini.google.com/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Gemini&lt;/a&gt;. Building, evaluating, and hosting custom&#xA;models is seen as challenging in Go (primarily due to the lack of frameworks&#xA;and libraries that support this in Python), but interview participants&#xA;distinguished between hobbyist use cases (e.g., playing around with custom&#xA;models at home) and business use cases. The hobbyist cases are dominated by&#xA;Python for all of the reasons enumerated above, but the business use cases are&#xA;more focused around reliability, accuracy, and performance while calling&#xA;hosted models. This is an area where Go can shine &lt;em&gt;without&lt;/em&gt; building a large&#xA;ecosystem of ML/AI/data science libraries, though we expect developers will&#xA;still benefit from documentation, best practice guidance, and examples.&lt;/p&gt;&#xA;&lt;p&gt;Because the field of GenAI is so novel, best practices are still being&#xA;identified and tested. Initial contextual interviews with developers have&#xA;suggested that one of their goals is to be prepared for a future in which&#xA;GenAI becomes a competitive advantage; by making some investment in this area&#xA;now, they hope to moderate future risk. They&amp;rsquo;re also still trying to&#xA;understand what GenAI systems might be helpful for and what the return on&#xA;investment (if any) may look like. Due to these unknowns, our early data&#xA;suggests that organizations (especially outside the tech industry) may be&#xA;hesitant to make long-term commitments here, and will instead pursue a lean or&#xA;scrappy approach until either a reliable use case with clear benefits emerges,&#xA;or their industry peers begin to make large, public investments in this space.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/python_usage.svg&#34; alt=&#34;Chart showing high usage of&#xA;Python to integrate with gen AI models&#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2024h1/go_python_pref.svg&#34; alt=&#34;Chart showing preference to use Go&#xA;rather than Python to integrate with gen AI models&#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2024h1/enable_go.svg&#34; alt=&#34;Chart of what would enable respondents&#xA;to use Go where they are currently using Python&#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2024h1/text_ml_challenge.svg&#34; alt=&#34;Chart of biggest challenges for&#xA;respondents integrating backend services with gen AI models&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;learn&#34;&gt;Learning challenges&lt;/h2&gt;&#xA;&lt;p&gt;In order to improve the experience of learning Go, we wanted to hear from&#xA;inexperienced Go developers, as well as those who might have already mastered&#xA;the basics on what they see as their biggest challenge to meeting their&#xA;learning goals. We also wanted to hear from developers who might primarily be&#xA;focused on helping others get started with Go rather than their own learning&#xA;goals, since they might have some insights on common challenges they see when&#xA;onboarding developers.&lt;/p&gt;&#xA;&lt;p&gt;Only 3% of respondents said that they were currently learning the basics of&#xA;Go. This isn&amp;rsquo;t too surprising, considering  most of our survey respondents&#xA;have at least a year of experience with Go. Meanwhile, 40% of respondents said&#xA;that they have already learned the basics but want to learn more advanced&#xA;topics and another 40% said that they help other developers learn Go. Only 15%&#xA;said they didn&amp;rsquo;t have any learning goals related to Go.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/learning_goal.svg&#34; alt=&#34;Chart of respondents&#39; learning&#xA;goals for Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;When we looked at more finely grained time segments of Go experience, we found&#xA;that 30% of those who&amp;rsquo;ve been using Go for less than three months say they&amp;rsquo;re&#xA;learning the basics of Go, while about two-thirds of them say that they&amp;rsquo;ve&#xA;already learned the basics. That&amp;rsquo;s good evidence that someone can at least&#xA;feel like they&amp;rsquo;ve learned the basics of Go in a short amount of time, but it&#xA;also means we don&amp;rsquo;t have as much feedback from this group who are at the&#xA;beginning of their learning journey.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/learning_goal_go_exp.svg&#34; alt=&#34;Chart of respondents&#39;&#xA;learning goals for Go split by finer units of time&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;To determine what kinds of learning materials might be most needed in the&#xA;community, we asked what kind of learning content respondents preferred for&#xA;topics related to software development. They were able to select multiple&#xA;options so the numbers here exceed 100%. 87% of respondents said they&#xA;preferred written content, which was by far the most preferred format. 52%&#xA;said they preferred video content, and in particular this format was more&#xA;often preferred by developers with less experience. This could indicate a&#xA;growing desire for learning content in video format. The less experienced&#xA;demographic did not prefer written content any less than other groups,&#xA;however.  &lt;a href=&#34;https://www.sciencedirect.com/science/article/abs/pii/S0360131514001353&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Providing both written and video formats together has been shown to&#xA;improve learning&#xA;outcomes&lt;/a&gt;&#xA;and &lt;a href=&#34;https://udlguidelines.cast.org/representation/perception&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;helps developers with different learning preferences and&#xA;abilities&lt;/a&gt;, which&#xA;could increase the accessibility of learning content in the Go community.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/learning_content_exp.svg&#34; alt=&#34;Chart of respondents&#39;&#xA;preferred formats for learning content, split by years of Go experience&#34;&#xA;class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;We asked respondents who said they had a learning goal related to Go what&#xA;their biggest challenge was to reaching their goal. This was intentionally&#xA;left broad enough that someone who was just getting started or who had already&#xA;mastered the basics could respond to this question. We also wanted to give&#xA;respondents the opportunity to tell us about a wide range of challenges, not&#xA;just topics they find difficult.&lt;/p&gt;&#xA;&lt;p&gt;Overwhelmingly, the most common challenge mentioned was a lack of time or&#xA;other personal limitations such as focus or motivation to learn or  (44%).&#xA;Although we can&amp;rsquo;t give respondents more time, we should be mindful when we&amp;rsquo;re&#xA;producing learning materials or introducing changes in the ecosystem that&#xA;users may be operating under significant time constraints. There may also be&#xA;opportunities for educators to produce resources that are &lt;a href=&#34;https://web.cortland.edu/frieda/id/IDtheories/26.html&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;digestible in&#xA;smaller portions&lt;/a&gt; or&#xA;&lt;a href=&#34;https://psychology.ucsd.edu/undergraduate-program/undergraduate-resources/academic-writing-resources/effective-studying/spaced-practice.html#:~:text=This%20is%20known%20as%20spaced,information%20and%20retain%20it%20longer.&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;at a regular&#xA;cadence&lt;/a&gt;&#xA;to keep learners motivated.&lt;/p&gt;&#xA;&lt;p&gt;Other than time, the top challenge was learning new concepts, idioms or best&#xA;practices that are unique to Go (11%). In particular, adapting to a statically&#xA;typed compiled language from Python or JavaScript and learning how to organize&#xA;Go code can be particularly challenging. Respondents also asked for more&#xA;examples (6%), both in documentation and real world applications to learn&#xA;from. Developers coming from a larger developer community expected to be able&#xA;to find more existing solutions and examples.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Moving from a language like Python to a statically typed, compiled language&#xA;has been challenging, but Go itself hasn&amp;rsquo;t been. I like to learn through&#xA;quick feedback, so Python&amp;rsquo;s REPL was great for that. So now I need to focus&#xA;on really reading documentation and examples to be able to learn. Some of&#xA;the documentation for Go is quite sparse and could do with more examples.&amp;rdquo;&#xA;&lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Respondent with less than 3 years of&#xA;experience with Go.&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;My main challenge is the lack of example projects for enterprise-level&#xA;applications. How to organize a big Go project is something I would like to&#xA;have more examples as reference. I would like to refactor the current&#xA;project I am working [on] to a more modular/clean architecture style, and I&#xA;find it difficult in Go due to lack of examples / a more opinionated&#xA;‘folder/package&amp;rsquo; reference.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Respondent with&#xA;1–2 years of experience with Go.&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;It&amp;rsquo;s a smaller ecosystem than I am used to so online searches don&amp;rsquo;t yield&#xA;as many results to specific issues. The resources that are out there are&#xA;incredibly helpful and I usually am able to solve issues eventually, it just&#xA;takes a little longer.&amp;quot;&lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Respondent with less&#xA;than 3 months of experience with Go.&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/text_learning_challenge.svg&#34; alt=&#34;Chart of biggest&#xA;challenges to reaching respondents&#39; learning goals&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;For respondents whose primary learning goal was to help others get started&#xA;with Go, we asked what might make it easier for developers to get started with&#xA;Go. We got a wide range of responses including documentation suggestions,&#xA;comments on difficult topics (e.g., using pointers or concurrency), as well as&#xA;requests for adding more familiar features from other languages. For&#xA;categories that made up less than 2% of responses, we lumped them into &amp;ldquo;Other&amp;rdquo;&#xA;responses. Interestingly, nobody mentioned &amp;ldquo;more time.&amp;rdquo; We think this is&#xA;because lack of time or motivation is most often a challenge when there isn&amp;rsquo;t&#xA;an immediate necessity to learn something new related to Go. For those helping&#xA;others get started with Go, there may be a business reason for doing so,&#xA;making it easier to prioritize, and hence &amp;ldquo;lack of time&amp;rdquo; is not as much of a&#xA;challenge.&lt;/p&gt;&#xA;&lt;p&gt;Consistent with the previous results, 16% of those who help others get started&#xA;with Go told us that new Go developers would benefit from having more&#xA;realistic examples or project-based exercises to learn from. They also saw the&#xA;need to help developers coming from other language ecosystems through&#xA;comparisons between them. &lt;a href=&#34;https://dl.acm.org/doi/abs/10.1145/3377811.3380352&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Previous research tells us that experience with one&#xA;programming language can interfere with learning a new&#xA;one&lt;/a&gt;, especially when new&#xA;concepts and tooling are different from what developers are used to. There are&#xA;existing resources that aim to address this issue (just try searching for&#xA;&amp;ldquo;Golang for [language] developers&amp;rdquo; for examples),  but it could be difficult&#xA;for new Go developers to search for concepts they don&amp;rsquo;t have the vocabulary&#xA;for yet or these kinds of resources might not adequately address specific&#xA;tasks. In the future we would like to learn more about how and when to present&#xA;language comparisons to facilitate learning new concepts.&lt;/p&gt;&#xA;&lt;p&gt;A related need that this group reported was more explanations behind Go&amp;rsquo;s&#xA;philosophy and best practices. It could be the case that learning not only&#xA;&lt;em&gt;what&lt;/em&gt; makes Go different but also &lt;em&gt;why&lt;/em&gt; would help new Go developers&#xA;understand new concepts or ways of doing tasks that might be different from&#xA;their previous experience.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/text_onboard_others.svg&#34; alt=&#34;Chart of ideas from&#xA;respondents  who help others get started with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;demographics&#34;&gt;Demographics&lt;/h2&gt;&#xA;&lt;p&gt;We ask similar demographic questions during each cycle of this survey so we&#xA;can understand how comparable the year-over-year results may be. For example,&#xA;if a majority of respondents reported having less than one year of experience&#xA;with Go in one survey cycle, it&amp;rsquo;d be very likely that any other differences in&#xA;results from prior cycles stem from this major demographic shift. We also use&#xA;these questions to provide comparisons between groups, such as satisfaction&#xA;according to how long respondents have been using Go.&lt;/p&gt;&#xA;&lt;p&gt;This year we introduced some minor changes to how we ask about experience with&#xA;Go to match the JetBrains developer survey. This allowed us to make&#xA;comparisons between our survey populations and facilitated data analysis.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/go_exp.svg&#34; alt=&#34;Chart of how long respondents have&#xA;been working with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;We saw some differences in experience level depending on how developers&#xA;discovered our survey. The population who responded to survey notifications in&#xA;VS Code skewed toward less experience with Go; we suspect this a reflection of&#xA;VS Code&amp;rsquo;s popularity with new Go developers, who may not be ready to invest in&#xA;an IDE license while they&amp;rsquo;re still learning. With respect to years of  Go&#xA;experience, the respondents randomly selected from GoLand are more similar to&#xA;our self-selected population who found the survey through the Go Blog. Seeing&#xA;consistencies between samples such as these allows us to more confidently&#xA;generalize findings to the rest of the community.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/go_exp_src.svg&#34; alt=&#34;Chart of how long respondents have&#xA;been working with Go, split by different sample sources&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;In addition to years of experience with Go, this year we also measured years&#xA;of professional coding experience. We were surprised to find that 26% of&#xA;respondents have 16 or more years of professional coding experience. For&#xA;comparison, the &lt;a href=&#34;https://www.jetbrains.com/lp/devecosystem-2023/demographics/#code_yrs&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;JetBrains Developer Survey&#xA;audience&lt;/a&gt;&#xA;from 2023 had a majority of respondents with 3–5 years of professional&#xA;experience. Having a more experienced demographic could affect differences in&#xA;responses. For example, we saw significant differences in what kinds of&#xA;learning content respondents with different levels of experience preferred.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/dev_exp.svg&#34; alt=&#34;Chart of respondents&#39; years of&#xA;professional developer experience&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;When we looked at our different samples, the self-selected group was even more&#xA;experienced than the randomly selected groups, with 29% having 16 or more&#xA;years of professional experience. This suggests that our self-selected group&#xA;is generally more experienced than our randomly selected groups and can help&#xA;explain some of the differences we see in this group.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/dev_exp_src.svg&#34; alt=&#34;Chart of respondents&#39; years of&#xA;professional developer experience&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;We introduced another demographic question during this cycle on employment&#xA;status to help us make comparisons with &lt;a href=&#34;https://www.jetbrains.com/lp/devecosystem-2023/demographics/#employment_status&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;JetBrains&amp;rsquo; Developer&#xA;Survey&lt;/a&gt;.&#xA;We found that 81% of respondents were fully employed, significantly more than&#xA;63% on the JetBrains survey. We also found significantly fewer students in our&#xA;population (4%) compared to 15% on the JetBrains survey. When we look at our&#xA;individual samples, we see a small but significant difference within our&#xA;respondents from VS Code, who are slightly less likely to be fully employed&#xA;and slightly more likely to be students. This makes sense given that VS Code&#xA;is free.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/employment.svg&#34; alt=&#34;Chart of respondents&#39; employment&#xA;status&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Similar to previous years, the most common use cases for Go were API/RPC&#xA;services (74%) and command line tools (63%). We&amp;rsquo;ve heard that Go&amp;rsquo;s built-in&#xA;HTTP server and concurrency primitives, ease of cross-compilation, and&#xA;single-binary deployments make Go a good choice for these kinds of&#xA;applications.&lt;/p&gt;&#xA;&lt;p&gt;We also looked for differences based on respondents&amp;rsquo; level of experience with&#xA;Go and organization size. More experienced Go developers reported building a&#xA;wider variety of applications in Go. This trend was consistent across every&#xA;category of app or service. We did not find any notable differences in what&#xA;respondents are building based on their organization size.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/what.svg&#34; alt=&#34;Chart of the types of things respondents&#xA;are building with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;firmographics&#34;&gt;Firmographics&lt;/h2&gt;&#xA;&lt;p&gt;We heard from respondents at a variety of different organizations. About 27%&#xA;worked at large organizations with 1,000 or more employees, 25% were from&#xA;midsize organizations of 100–1,000 employees, and 43% worked at smaller&#xA;organizations with less than 100 employees. As in previous years, the most&#xA;common industry people work in was technology (48%) while the second most&#xA;common was financial services (13%) .&lt;/p&gt;&#xA;&lt;p&gt;This is statistically unchanged from the past few Go Developer Surveys—we&#xA;continue to hear from people in different countries and in organizations of&#xA;different sizes and industries at consistent rates year after year.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/org_size.svg&#34; alt=&#34;Chart of the different organization&#xA;sizes where respondents use Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/industry.svg&#34; alt=&#34;Chart of the different industries&#xA;where respondents use Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/location.svg&#34; alt=&#34;Chart of countries or regions where&#xA;respondents are located&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;methodology&#34;&gt;Methodology&lt;/h2&gt;&#xA;&lt;p&gt;Prior to 2021, we announced the survey primarily through the Go Blog, where it&#xA;was picked up on various social channels like Twitter, Reddit, or Hacker News.&#xA;In 2021 we introduced a new way to recruit respondents by using the VS Code Go&#xA;plugin to randomly select users to be shown a prompt asking if they&amp;rsquo;d like to&#xA;participate in the survey. This created a random sample that we used to&#xA;compare the self-selected respondents from our traditional channels and helped&#xA;identify potential effects of &lt;a href=&#34;https://en.wikipedia.org/wiki/Self-selection_bias&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;self-selection&#xA;bias&lt;/a&gt;. For this cycle, our&#xA;friends at JetBrains generously provided us with an additional random sample&#xA;by prompting a random subset of GoLand users to take the survey!&lt;/p&gt;&#xA;&lt;p&gt;64% of survey respondents &amp;ldquo;self-selected&amp;rdquo; to take the survey, meaning they&#xA;found it on the Go blog or other social Go channels. People who don&amp;rsquo;t follow&#xA;these channels are less likely to learn about the survey from them, and in&#xA;some cases, they respond differently than people who do closely follow them.&#xA;For example, they might be new to the Go community and not yet aware of the Go&#xA;blog. About 36% of respondents were randomly sampled, meaning they responded&#xA;to the survey after seeing a prompt in VS Code (25%) or GoLand (11%). Over the&#xA;period of January 23 &amp;ndash; February 13, there was roughly a 10% chance that users&#xA;would have seen this prompt. By examining how the randomly sampled groups&#xA;differ from the self-selected responses, as well as from each other, we&amp;rsquo;re&#xA;able to more confidently generalize findings to the larger community of Go&#xA;developers.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2024h1/source.svg&#34; alt=&#34;Chart of different sources of survey&#xA;respondents&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-read-these-results&#34;&gt;How to read these results&lt;/h3&gt;&#xA;&lt;p&gt;Throughout this report we use charts of survey responses to provide supporting&#xA;evidence for our findings. All of these charts use a similar format. The title&#xA;is the exact question that survey respondents saw. Unless otherwise noted,&#xA;questions were multiple choice and participants could only select a single&#xA;response choice; each chart&amp;rsquo;s subtitle will tell the reader if the question&#xA;allowed multiple response choices or was an open-ended text box instead of a&#xA;multiple choice question. For charts of open-ended text responses, a Go team&#xA;member read and manually categorized all of the responses. Many open-ended&#xA;questions elicited a wide variety of responses; to keep the chart sizes&#xA;reasonable, we condensed them to a maximum of the top 10-12 themes, with&#xA;additional themes all grouped under &amp;ldquo;Other&amp;rdquo;. The percentage labels shown in&#xA;charts are rounded to the nearest integer (e.g., 1.4% and 0.8% will both be&#xA;displayed as 1%), but the length of each bar and row ordering are based on the&#xA;unrounded values.&lt;/p&gt;&#xA;&lt;p&gt;To help readers understand the weight of evidence underlying each finding, we&#xA;included error bars showing the 95% &lt;a href=&#34;https://en.wikipedia.org/wiki/Confidence_interval&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;confidence&#xA;interval&lt;/a&gt; for responses;&#xA;narrower bars indicate increased confidence. Sometimes two or more responses&#xA;have overlapping error bars, which means the relative order of those responses&#xA;is not statistically meaningful (i.e., the responses are effectively tied).&#xA;The lower right of each chart shows the number of people whose responses are&#xA;included in the chart, in the form &amp;ldquo;n = [number of respondents]&amp;rdquo;. In cases&#xA;where we found interesting differences in responses between groups, (e.g.,&#xA;years of experience, organization size, or sample source) we showed a&#xA;color-coded breakdown of the differences.&lt;/p&gt;&#xA;&lt;h2 id=&#34;closing&#34;&gt;Closing&lt;/h2&gt;&#xA;&lt;p&gt;And that&amp;rsquo;s it for our semi-annual Go Developer Survey. Many thanks to everyone&#xA;who shared their thoughts on Go and everyone who contributed to making this&#xA;survey happen! It means the world to us and truly helps us improve Go.&lt;/p&gt;&#xA;&lt;p&gt;This year we&amp;rsquo;re also excited to announce the forthcoming release of this survey&amp;rsquo;s&#xA;dataset. We expect to share this anonymized data by the end of April, allowing&#xA;anyone to slice and dice survey responses as needed to answer their own&#xA;questions about the Go ecosystem.&lt;/p&gt;&#xA;&lt;p&gt;Updated 2024-05-03: We unfortunately need to delay the release of this&#xA;dataset. We&amp;rsquo;re still working to make this happen, but we don&amp;rsquo;t expect to be&#xA;able to share it until the second half of 2024.&lt;/p&gt;&#xA;&lt;p&gt;&amp;mdash; Alice and Todd (on behalf of the Go team at Google)&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;Article prevnext&#34;&gt;&#xA;    &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;        &lt;p&gt;&#xA;        &#xA;          &#xA;            &lt;b&gt;Next article: &lt;/b&gt;&lt;a href=&#34;/blog/randv2&#34;&gt;Evolving the Go Standard Library with math/rand/v2&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &#xA;          &#xA;            &lt;b&gt;Previous article: &lt;/b&gt;&lt;a href=&#34;/blog/execution-traces-2024&#34;&gt;More powerful Go execution traces&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &lt;b&gt;&lt;a href=&#34;/blog/all&#34;&gt;Blog Index&lt;/a&gt;&lt;/b&gt;&#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;    &lt;/div&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script src=&#34;/js/jquery.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/playground.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/play.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/godocs.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;</content></entry><entry><title>More powerful Go execution traces</title><id>tag:blog.golang.org,2013:blog.golang.org/execution-traces-2024</id><link rel="alternate" href="https://go.dev/blog/execution-traces-2024"></link><published>2024-03-14T00:00:00+00:00</published><updated>2024-03-14T00:00:00+00:00</updated><author><name></name></author><summary type="html">New features and improvements to execution traces from the last year.</summary><content type="html">&#xA;&lt;div id=&#34;blog&#34;&gt;&lt;div id=&#34;content&#34;&gt;&#xA;  &lt;div id=&#34;content&#34;&gt;&#xA;&#xA;    &lt;div class=&#34;Article&#34; data-slug=&#34;/blog/execution-traces-2024&#34;&gt;&#xA;    &#xA;    &lt;h1 class=&#34;small&#34;&gt;&lt;a href=&#34;/blog/&#34;&gt;The Go Blog&lt;/a&gt;&lt;/h1&gt;&#xA;    &#xA;&#xA;    &lt;h1&gt;More powerful Go execution traces&lt;/h1&gt;&#xA;      &#xA;      &lt;p class=&#34;author&#34;&gt;&#xA;      Michael Knyszek&lt;br&gt;&#xA;      14 March 2024&#xA;      &lt;/p&gt;&#xA;      &#xA;      &lt;p&gt;The &lt;a href=&#34;/pkg/runtime/trace&#34;&gt;runtime/trace&lt;/a&gt; package contains a powerful tool for understanding and&#xA;troubleshooting Go programs.&#xA;The functionality within allows one to produce a trace of each goroutine&amp;rsquo;s execution over some&#xA;time period.&#xA;With the &lt;a href=&#34;/pkg/cmd/trace&#34;&gt;&lt;code&gt;go tool trace&lt;/code&gt; command&lt;/a&gt; (or the excellent open source&#xA;&lt;a href=&#34;https://gotraceui.dev/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;gotraceui tool&lt;/a&gt;), one may then visualize and explore the data within these&#xA;traces.&lt;/p&gt;&#xA;&lt;p&gt;The magic of a trace is that it can easily reveal things about a program that are hard to see in&#xA;other ways.&#xA;For example, a concurrency bottleneck where lots of goroutines block on the same channel might be&#xA;quite difficult to see in a CPU profile, because there&amp;rsquo;s no execution to sample.&#xA;But in an execution trace, the &lt;em&gt;lack&lt;/em&gt; of execution will show up with amazing clarity, and the stack&#xA;traces of blocked goroutines will quickly point at the culprit.&lt;/p&gt;&#xA;&lt;div class=&#34;image&#34;&gt;&#xA;  &lt;img src=&#34;execution-traces-2024/gotooltrace.png&#34; alt=&#34;&#34;&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;Go developers are even able to instrument their own programs with &lt;a href=&#34;/pkg/runtime/trace#Task&#34;&gt;tasks&lt;/a&gt;,&#xA;&lt;a href=&#34;/pkg/runtime/trace#WithRegion&#34;&gt;regions&lt;/a&gt;, and &lt;a href=&#34;/pkg/runtime/trace#Log&#34;&gt;logs&lt;/a&gt; that&#xA;they can use to correlate their higher-level concerns with lower-level execution details.&lt;/p&gt;&#xA;&lt;h2 id=&#34;issues&#34;&gt;Issues&lt;/h2&gt;&#xA;&lt;p&gt;Unfortunately, the wealth of information in execution traces can often be out of reach.&#xA;Four big issues with traces have historically gotten in the way.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Traces had high overheads.&lt;/li&gt;&#xA;&lt;li&gt;Traces didn&amp;rsquo;t scale well, and could become too big to analyze.&lt;/li&gt;&#xA;&lt;li&gt;It was often unclear when to start tracing to capture a specific bad behavior.&lt;/li&gt;&#xA;&lt;li&gt;Only the most adventurous gophers could programmatically analyze traces, given the lack of a&#xA;public package for parsing and interpreting execution traces.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If you&amp;rsquo;ve used traces in the last few years, you&amp;rsquo;ve likely been frustrated by one or more of these&#xA;problems.&#xA;But we&amp;rsquo;re excited to share that over the last two Go releases we&amp;rsquo;ve made big progress in all four&#xA;of these areas.&lt;/p&gt;&#xA;&lt;h2 id=&#34;low-overhead-tracing&#34;&gt;Low-overhead tracing&lt;/h2&gt;&#xA;&lt;p&gt;Prior to Go 1.21, the run-time overhead of tracing was somewhere between 10–20% CPU for many&#xA;applications, which limits tracing to situational usage, rather than continuous usage like CPU&#xA;profiling.&#xA;It turned out that much of the cost of tracing came down to tracebacks.&#xA;Many events produced by the runtime have stack traces attached, which are invaluable to actually&#xA;identifying what goroutines were doing at key moments in their execution.&lt;/p&gt;&#xA;&lt;p&gt;Thanks to work by Felix Geisendörfer and Nick Ripley on optimizing the efficiency of tracebacks,&#xA;the run-time CPU overhead of execution traces has been cut dramatically, down to 1–2% for many&#xA;applications.&#xA;You can read more about the work done here in &lt;a href=&#34;https://blog.felixge.de/reducing-gos-execution-tracer-overhead-with-frame-pointer-unwinding/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Felix&amp;rsquo;s great blog&#xA;post&lt;/a&gt;&#xA;on the topic.&lt;/p&gt;&#xA;&lt;h2 id=&#34;scalable-traces&#34;&gt;Scalable traces&lt;/h2&gt;&#xA;&lt;p&gt;The trace format and its events were designed around relatively efficient emission, but required&#xA;tooling to parse and keep around the state of the entirety of a trace.&#xA;A few hundred MiB trace could require several GiB of RAM to analyze!&lt;/p&gt;&#xA;&lt;p&gt;This issue is unfortunately fundamental to how traces are generated.&#xA;To keep run-time overheads low, all events are written to the equivalent of thread-local buffers.&#xA;But this means events appear out of their true order, and the burden is placed on the trace&#xA;tooling to figure out what really happened.&lt;/p&gt;&#xA;&lt;p&gt;The key insight to making traces scale while keeping overheads low was to occasionally split the&#xA;trace being generated.&#xA;Each split point would behave a bit like simultaneously disabling and reenabling tracing in one&#xA;go.&#xA;All the trace data so far would represent a complete and self-contained trace, while the new trace&#xA;data would seamlessly pick up from where it left off.&lt;/p&gt;&#xA;&lt;p&gt;As you might imagine, fixing this required &lt;a href=&#34;/issue/60773&#34;&gt;rethinking and rewriting a lot of the foundation of&#xA;the trace implementation&lt;/a&gt; in the runtime.&#xA;We&amp;rsquo;re happy to say that the work landed in Go 1.22 and is now generally available.&#xA;&lt;a href=&#34;/doc/go1.22#runtime/trace&#34;&gt;A lot of nice improvements&lt;/a&gt; came with the rewrite, including some&#xA;improvements to the &lt;a href=&#34;/doc/go1.22#trace&#34;&gt;&lt;code&gt;go tool trace&lt;/code&gt; command&lt;/a&gt; as well.&#xA;The gritty details are all in the &lt;a href=&#34;https://github.com/golang/proposal/blob/master/design/60773-execution-tracer-overhaul.md&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;design&#xA;document&lt;/a&gt;,&#xA;if you&amp;rsquo;re curious.&lt;/p&gt;&#xA;&lt;p&gt;(Note: &lt;code&gt;go tool trace&lt;/code&gt; still loads the full trace into memory, but &lt;a href=&#34;/issue/65315&#34;&gt;removing this&#xA;limitation&lt;/a&gt; for traces produced by Go 1.22+ programs is now feasible.)&lt;/p&gt;&#xA;&lt;h2 id=&#34;flight-recording&#34;&gt;Flight recording&lt;/h2&gt;&#xA;&lt;p&gt;Suppose you work on a web service and an RPC took a very long time.&#xA;You couldn&amp;rsquo;t start tracing at the point you knew the RPC was already taking a while, because the&#xA;root cause of the slow request already happened and wasn&amp;rsquo;t recorded.&lt;/p&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a technique that can help with this called flight recording, which you may already be&#xA;familiar with from other programming environments.&#xA;The insight with flight recording is to have tracing on continuously and always keep the most&#xA;recent trace data around, just in case.&#xA;Then, once something interesting happens, the program can just write out whatever it has!&lt;/p&gt;&#xA;&lt;p&gt;Before traces could be split, this was pretty much a non-starter.&#xA;But because continuous tracing is now viable thanks to low overheads, and the fact that the runtime&#xA;can now split traces any time it needs, it turns out it was straightforward to implement flight&#xA;recording.&lt;/p&gt;&#xA;&lt;p&gt;As a result, we&amp;rsquo;re happy to announce a flight recorder experiment, available in the&#xA;&lt;a href=&#34;/pkg/golang.org/x/exp/trace#FlightRecorder&#34;&gt;golang.org/x/exp/trace package&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Please try it out!&#xA;Below is an example that sets up flight recording to capture a long HTTP request to get you started.&lt;/p&gt;&#xA;&lt;div class=&#34;code&#34;&gt;&#xA;&lt;pre&gt;    &lt;span class=&#34;comment&#34;&gt;// Set up the flight recorder.&lt;/span&gt;&#xA;    fr := trace.NewFlightRecorder()&#xA;    fr.Start()&#xA;&#xA;    &lt;span class=&#34;comment&#34;&gt;// Set up and run an HTTP server.&lt;/span&gt;&#xA;    var once sync.Once&#xA;    http.HandleFunc(&amp;#34;/my-endpoint&amp;#34;, func(w http.ResponseWriter, r *http.Request) {&#xA;        start := time.Now()&#xA;&#xA;        &lt;span class=&#34;comment&#34;&gt;// Do the work...&lt;/span&gt;&#xA;        doWork(w, r)&#xA;&#xA;        &lt;span class=&#34;comment&#34;&gt;// We saw a long request. Take a snapshot!&lt;/span&gt;&#xA;        if time.Since(start) &amp;gt; 300*time.Millisecond {&#xA;            &lt;span class=&#34;comment&#34;&gt;// Do it only once for simplicity, but you can take more than one.&lt;/span&gt;&#xA;            once.Do(func() {&#xA;                &lt;span class=&#34;comment&#34;&gt;// Grab the snapshot.&lt;/span&gt;&#xA;                var b bytes.Buffer&#xA;                _, err = fr.WriteTo(&amp;amp;b)&#xA;                if err != nil {&#xA;                    log.Print(err)&#xA;                    return&#xA;                }&#xA;                &lt;span class=&#34;comment&#34;&gt;// Write it to a file.&lt;/span&gt;&#xA;                if err := os.WriteFile(&amp;#34;trace.out&amp;#34;, b.Bytes(), 0o755); err != nil {&#xA;                    log.Print(err)&#xA;                    return&#xA;                }&#xA;            })&#xA;        }&#xA;    })&#xA;    log.Fatal(http.ListenAndServe(&amp;#34;:8080&amp;#34;, nil))&#xA;&lt;/pre&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;If you have any feedback, positive or negative, please share it to the &lt;a href=&#34;/issue/63185&#34;&gt;proposal&#xA;issue&lt;/a&gt;!&lt;/p&gt;&#xA;&lt;h2 id=&#34;trace-reader-api&#34;&gt;Trace reader API&lt;/h2&gt;&#xA;&lt;p&gt;Along with the trace implementation rewrite came an effort to clean up the other trace internals,&#xA;like &lt;code&gt;go tool trace&lt;/code&gt;.&#xA;This spawned an attempt to create a trace reader API that was good enough to share and that could&#xA;make traces more accessible.&lt;/p&gt;&#xA;&lt;p&gt;Just like the flight recorder, we&amp;rsquo;re happy to announce that we also have an experimental trace reader&#xA;API that we&amp;rsquo;d like to share.&#xA;It&amp;rsquo;s available in the &lt;a href=&#34;/pkg/golang.org/x/exp/trace#Reader&#34;&gt;same package as the flight recorder,&#xA;golang.org/x/exp/trace&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;We think it&amp;rsquo;s good enough to start building things on top of, so please try it out!&#xA;Below is an example that measures the proportion of goroutine block events that blocked to wait on&#xA;the network.&lt;/p&gt;&#xA;&lt;div class=&#34;code&#34;&gt;&#xA;&lt;pre&gt;    &lt;span class=&#34;comment&#34;&gt;// Start reading from STDIN.&lt;/span&gt;&#xA;    r, err := trace.NewReader(os.Stdin)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    var blocked int&#xA;    var blockedOnNetwork int&#xA;    for {&#xA;        &lt;span class=&#34;comment&#34;&gt;// Read the event.&lt;/span&gt;&#xA;        ev, err := r.ReadEvent()&#xA;        if err == io.EOF {&#xA;            break&#xA;        } else if err != nil {&#xA;            log.Fatal(err)&#xA;        }&#xA;&#xA;        &lt;span class=&#34;comment&#34;&gt;// Process it.&lt;/span&gt;&#xA;        if ev.Kind() == trace.EventStateTransition {&#xA;            st := ev.StateTransition()&#xA;            if st.Resource.Kind == trace.ResourceGoroutine {&#xA;                from, to := st.Goroutine()&#xA;&#xA;                &lt;span class=&#34;comment&#34;&gt;// Look for goroutines blocking, and count them.&lt;/span&gt;&#xA;                if from.Executing() &amp;amp;&amp;amp; to == trace.GoWaiting {&#xA;                    blocked++&#xA;                    if strings.Contains(st.Reason, &amp;#34;network&amp;#34;) {&#xA;                        blockedOnNetwork++&#xA;                    }&#xA;                }&#xA;            }&#xA;        }&#xA;    }&#xA;    &lt;span class=&#34;comment&#34;&gt;// Print what we found.&lt;/span&gt;&#xA;    p := 100 * float64(blockedOnNetwork) / float64(blocked)&#xA;    fmt.Printf(&amp;#34;%2.3f%% instances of goroutines blocking were to block on the network\n&amp;#34;, p)&#xA;&lt;/pre&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;And just like the flight recorder, there&amp;rsquo;s a &lt;a href=&#34;/issue/62627&#34;&gt;proposal issue&lt;/a&gt; that would&#xA;be a great place to leave feedback!&lt;/p&gt;&#xA;&lt;p&gt;We&amp;rsquo;d like to quickly call out Dominik Honnef as someone who tried it out early, provided great&#xA;feedback, and has contributed support for older trace versions to the API.&lt;/p&gt;&#xA;&lt;h2 id=&#34;thank-you&#34;&gt;Thank you!&lt;/h2&gt;&#xA;&lt;p&gt;This work was completed, in no small part, thanks to the help of the those in the &lt;a href=&#34;/issue/57175&#34;&gt;diagnostics&#xA;working group&lt;/a&gt;, started over a year ago as a collaboration between stakeholders from&#xA;across the Go community, and open to the public.&lt;/p&gt;&#xA;&lt;p&gt;We&amp;rsquo;d like to take a moment to thank those community members who have attended the diagnostic&#xA;meetings regularly over the last year: Felix Geisendörfer, Nick Ripley, Rhys Hiltner, Dominik&#xA;Honnef, Bryan Boreham, thepudds.&lt;/p&gt;&#xA;&lt;p&gt;The discussions, feedback, and work you all put in have been instrumental to getting us to where we&#xA;are today.&#xA;Thank you!&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;Article prevnext&#34;&gt;&#xA;    &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;        &lt;p&gt;&#xA;        &#xA;          &#xA;            &lt;b&gt;Next article: &lt;/b&gt;&lt;a href=&#34;/blog/survey2024-h1-results&#34;&gt;Go Developer Survey 2024 H1 Results&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &#xA;          &#xA;            &lt;b&gt;Previous article: &lt;/b&gt;&lt;a href=&#34;/blog/generic-slice-functions&#34;&gt;Robust generic functions on slices&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &lt;b&gt;&lt;a href=&#34;/blog/all&#34;&gt;Blog Index&lt;/a&gt;&lt;/b&gt;&#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;    &lt;/div&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script src=&#34;/js/jquery.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/playground.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/play.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/godocs.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;</content></entry><entry><title>Robust generic functions on slices</title><id>tag:blog.golang.org,2013:blog.golang.org/generic-slice-functions</id><link rel="alternate" href="https://go.dev/blog/generic-slice-functions"></link><published>2024-02-22T00:00:00+00:00</published><updated>2024-02-22T00:00:00+00:00</updated><author><name></name></author><summary type="html">Avoiding memory leaks in the slices package.</summary><content type="html">&#xA;&lt;div id=&#34;blog&#34;&gt;&lt;div id=&#34;content&#34;&gt;&#xA;  &lt;div id=&#34;content&#34;&gt;&#xA;&#xA;    &lt;div class=&#34;Article&#34; data-slug=&#34;/blog/generic-slice-functions&#34;&gt;&#xA;    &#xA;    &lt;h1 class=&#34;small&#34;&gt;&lt;a href=&#34;/blog/&#34;&gt;The Go Blog&lt;/a&gt;&lt;/h1&gt;&#xA;    &#xA;&#xA;    &lt;h1&gt;Robust generic functions on slices&lt;/h1&gt;&#xA;      &#xA;      &lt;p class=&#34;author&#34;&gt;&#xA;      Valentin Deleplace&lt;br&gt;&#xA;      22 February 2024&#xA;      &lt;/p&gt;&#xA;      &#xA;      &lt;p&gt;The &lt;a href=&#34;/pkg/slices&#34;&gt;slices&lt;/a&gt; package provides functions that work for slices of any type.&#xA;In this blog post we&amp;rsquo;ll discuss how you can use these functions more effectively by understanding how slices are represented in memory and how that affects the garbage collector, and we&amp;rsquo;ll cover how we recently adjusted these functions to make them less surprising.&lt;/p&gt;&#xA;&lt;p&gt;With &lt;a href=&#34;/blog/deconstructing-type-parameters&#34;&gt;Type parameters&lt;/a&gt; we can write functions like &lt;a href=&#34;/pkg/slices#Index&#34;&gt;slices.Index&lt;/a&gt; once for all types of slices of comparable elements:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;// Index returns the index of the first occurrence of v in s,&#xA;// or -1 if not present.&#xA;func Index[S ~[]E, E comparable](s S, v E) int {&#xA;    for i := range s {&#xA;        if v == s[i] {&#xA;            return i&#xA;        }&#xA;    }&#xA;    return -1&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;It is no longer necessary to implement &lt;code&gt;Index&lt;/code&gt; again for each different type of element.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;/pkg/slices&#34;&gt;slices&lt;/a&gt; package contains many such helpers to perform common operations on slices:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;    s := []string{&amp;quot;Bat&amp;quot;, &amp;quot;Fox&amp;quot;, &amp;quot;Owl&amp;quot;, &amp;quot;Fox&amp;quot;}&#xA;    s2 := slices.Clone(s)&#xA;    slices.Sort(s2)&#xA;    fmt.Println(s2) // [Bat Fox Fox Owl]&#xA;    s2 = slices.Compact(s2)&#xA;    fmt.Println(s2)                  // [Bat Fox Owl]&#xA;    fmt.Println(slices.Equal(s, s2)) // false&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Several new functions (&lt;code&gt;Insert&lt;/code&gt;, &lt;code&gt;Replace&lt;/code&gt;, &lt;code&gt;Delete&lt;/code&gt;, etc.) modify the slice. To understand how they work, and how to properly use them, we need to examine the underlying structure of slices.&lt;/p&gt;&#xA;&lt;p&gt;A slice is a view of a portion of an array. &lt;a href=&#34;/blog/slices-intro&#34;&gt;Internally&lt;/a&gt;, a slice contains a pointer, a length, and a capacity. Two slices can have the same underlying array, and can view overlapping portions.&lt;/p&gt;&#xA;&lt;p&gt;For example, this slice &lt;code&gt;s&lt;/code&gt; is a view on 4 elements of an array of size 6:&lt;/p&gt;&#xA;&lt;div class=&#34;image&#34;&gt;&#xA;  &lt;img src=&#34;generic-slice-functions/1_sample_slice_4_6.svg&#34; width=&#34;450&#34; alt=&#34;&#34;&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;If a function changes the length of a slice passed as a parameter, then it needs to return a new slice to the caller. The underlying array may remain the same if it doesn&amp;rsquo;t have to grow. This explains why &lt;a href=&#34;/blog/slices&#34;&gt;append&lt;/a&gt; and &lt;code&gt;slices.Compact&lt;/code&gt; return a value, but &lt;code&gt;slices.Sort&lt;/code&gt;, which merely reorders the elements, does not.&lt;/p&gt;&#xA;&lt;p&gt;Consider the task of deleting a portion of a slice. Prior to generics, the standard way to delete the portion &lt;code&gt;s[2:5]&lt;/code&gt; from the slice &lt;code&gt;s&lt;/code&gt; was to call the &lt;a href=&#34;/ref/spec#Appending_and_copying_slices&#34;&gt;append&lt;/a&gt; function to copy the end portion over the middle portion:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;s = append(s[:2], s[5:]...)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The syntax was complex and error-prone, involving subslices and a variadic parameter. We added &lt;a href=&#34;/pkg/slices#Delete&#34;&gt;slice.Delete&lt;/a&gt; to make it easier to delete elements:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;func Delete[S ~[]E, E any](s S, i, j int) S {&#xA;       return append(s[:i], s[j:]...)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The one-line function &lt;code&gt;Delete&lt;/code&gt; more clearly expresses the programmer&amp;rsquo;s intent. Let’s consider a slice &lt;code&gt;s&lt;/code&gt; of length 6 and capacity 8, containing pointers:&lt;/p&gt;&#xA;&lt;div class=&#34;image&#34;&gt;&#xA;  &lt;img src=&#34;generic-slice-functions/2_sample_slice_6_8.svg&#34; width=&#34;600&#34; alt=&#34;&#34;&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;This call deletes the elements at &lt;code&gt;s[2]&lt;/code&gt;, &lt;code&gt;s[3]&lt;/code&gt;, &lt;code&gt;s[4]&lt;/code&gt;  from the slice &lt;code&gt;s&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;s = slices.Delete(s, 2, 5)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div class=&#34;image&#34;&gt;&#xA;  &lt;img src=&#34;generic-slice-functions/3_delete_s_2_5.svg&#34; width=&#34;600&#34; alt=&#34;&#34;&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;The gap at the indices 2, 3, 4 is filled by shifting the element &lt;code&gt;s[5]&lt;/code&gt; to the left, and setting the new length to &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;Delete&lt;/code&gt; need not allocate a new array, as it shifts the elements in place. Like &lt;code&gt;append&lt;/code&gt;, it returns a new slice. Many other functions in the &lt;code&gt;slices&lt;/code&gt; package follow this pattern, including &lt;code&gt;Compact&lt;/code&gt;, &lt;code&gt;CompactFunc&lt;/code&gt;, &lt;code&gt;DeleteFunc&lt;/code&gt;, &lt;code&gt;Grow&lt;/code&gt;, &lt;code&gt;Insert&lt;/code&gt;, and &lt;code&gt;Replace&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;When calling these functions we must consider the original slice invalid, because the underlying array has been modified. It would be a mistake to call the function but ignore the return value:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;    slices.Delete(s, 2, 5) // incorrect!&#xA;    // s still has the same length, but modified contents&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;a-problem-of-unwanted-liveness&#34;&gt;A problem of unwanted liveness&lt;/h2&gt;&#xA;&lt;p&gt;Before Go 1.22, &lt;code&gt;slices.Delete&lt;/code&gt; didn&amp;rsquo;t modify the elements between the new and original lengths of the slice. While the returned slice wouldn&amp;rsquo;t include these elements, the &amp;ldquo;gap&amp;rdquo; created at the end of the original, now-invalidated slice continued to hold onto them. These elements could contain pointers to large objects (a 20MB image), and the garbage collector would not release the memory associated with these objects. This resulted in a memory leak that could lead to significant performance issues.&lt;/p&gt;&#xA;&lt;p&gt;In this above example, we’re successfully deleting the pointers &lt;code&gt;p2&lt;/code&gt;, &lt;code&gt;p3&lt;/code&gt;, &lt;code&gt;p4&lt;/code&gt; from &lt;code&gt;s[2:5]&lt;/code&gt;, by shifting one element to the left. But &lt;code&gt;p3&lt;/code&gt; and &lt;code&gt;p4&lt;/code&gt; are still present in the underlying array, beyond the new length of &lt;code&gt;s&lt;/code&gt;. The garbage collector won’t reclaim them. Less obviously, &lt;code&gt;p5&lt;/code&gt; is not one of the deleted elements, but its memory may still leak because of the &lt;code&gt;p5&lt;/code&gt; pointer kept in the gray part of the array.&lt;/p&gt;&#xA;&lt;p&gt;This could be confusing for developers, if they were not aware that &amp;ldquo;invisible&amp;rdquo; elements were still using memory.&lt;/p&gt;&#xA;&lt;p&gt;So we had two options:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Either keep the efficient implementation of &lt;code&gt;Delete&lt;/code&gt;. Let users set obsolete pointers to &lt;code&gt;nil&lt;/code&gt; themselves, if they want to make sure the values pointed to can be freed.&lt;/li&gt;&#xA;&lt;li&gt;Or change &lt;code&gt;Delete&lt;/code&gt; to always set the obsolete elements to zero. This is extra work, making &lt;code&gt;Delete&lt;/code&gt; slightly less efficient. Zeroing pointers (setting them to &lt;code&gt;nil&lt;/code&gt;) enables the garbage collection of the objects, when they become otherwise unreachable.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;It was not obvious which option was best. The first one provided performance by default, and the second one provided memory frugality by default.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-fix&#34;&gt;The fix&lt;/h2&gt;&#xA;&lt;p&gt;A key observation is that &amp;ldquo;setting the obsolete pointers to &lt;code&gt;nil&lt;/code&gt;&amp;rdquo; is not as easy as it seems. In fact, this task is so error-prone that we should not put the burden on the user to write it. Out of pragmatism, we chose to modify the implementation of the five functions &lt;code&gt;Compact&lt;/code&gt;, &lt;code&gt;CompactFunc&lt;/code&gt;, &lt;code&gt;Delete&lt;/code&gt;, &lt;code&gt;DeleteFunc&lt;/code&gt;, &lt;code&gt;Replace&lt;/code&gt; to &amp;ldquo;clear the tail&amp;rdquo;. As a nice side effect, the cognitive load is reduced and users now don’t need to worry about these memory leaks.&lt;/p&gt;&#xA;&lt;p&gt;In Go 1.22, this is what the memory looks like after calling Delete:&lt;/p&gt;&#xA;&lt;div class=&#34;image&#34;&gt;&#xA;  &lt;img src=&#34;generic-slice-functions/4_delete_s_2_5_nil.svg&#34; width=&#34;600&#34; alt=&#34;&#34;&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;The code changed in the five functions uses the new built-in function &lt;a href=&#34;/pkg/builtin#clear&#34;&gt;clear&lt;/a&gt; (Go 1.21) to set the obsolete elements to the zero value of the element type of &lt;code&gt;s&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;image&#34;&gt;&#xA;  &lt;img src=&#34;generic-slice-functions/5_Delete_diff.png&#34; width=&#34;800&#34; alt=&#34;&#34;&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;The zero value of &lt;code&gt;E&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt; when &lt;code&gt;E&lt;/code&gt; is a type of pointer, slice, map, chan, or interface.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tests-failing&#34;&gt;Tests failing&lt;/h2&gt;&#xA;&lt;p&gt;This change has led to some tests that passed in Go 1.21 now failing in Go 1.22, when the slices functions are used incorrectly. This is good news. When you have a bug, tests should let you know.&lt;/p&gt;&#xA;&lt;p&gt;If you ignore the return value of &lt;code&gt;Delete&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;slices.Delete(s, 2, 3)  // !! INCORRECT !!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;then you may incorrectly assume that &lt;code&gt;s&lt;/code&gt; does not contain any nil pointer. &lt;a href=&#34;/play/p/NDHuO8vINHv&#34;&gt;Example in the Go Playground&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you ignore the return value of &lt;code&gt;Compact&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;slices.Sort(s) // correct&#xA;slices.Compact(s) // !! INCORRECT !!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;then you may incorrectly assume that &lt;code&gt;s&lt;/code&gt; is properly sorted and compacted. &lt;a href=&#34;/play/p/eFQIekiwlnu&#34;&gt;Example&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you assign the return value of &lt;code&gt;Delete&lt;/code&gt; to another variable, and keep using the original slice:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;u := slices.Delete(s, 2, 3)  // !! INCORRECT, if you keep using s !!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;then you may incorrectly assume that &lt;code&gt;s&lt;/code&gt; does not contain any nil pointer. &lt;a href=&#34;/play/p/rDxWmJpLOVO&#34;&gt;Example&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you accidentally shadow the slice variable, and keep using the original slice:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;s := slices.Delete(s, 2, 3)  // !! INCORRECT, using := instead of = !!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;then you may incorrectly assume that &lt;code&gt;s&lt;/code&gt; does not contain any nil pointer. &lt;a href=&#34;/play/p/KSpVpkX8sOi&#34;&gt;Example&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;The API of the &lt;code&gt;slices&lt;/code&gt; package is a net improvement over the traditional pre-generics syntax to delete or insert elements.&lt;/p&gt;&#xA;&lt;p&gt;We encourage developers to use the new functions, while avoiding the &amp;ldquo;gotchas&amp;rdquo; listed above.&lt;/p&gt;&#xA;&lt;p&gt;Thanks to the recent changes in the implementation, a class of memory leaks is automatically avoided, without any change to the API, and with no extra work for the developers.&lt;/p&gt;&#xA;&lt;h2 id=&#34;further-reading&#34;&gt;Further reading&lt;/h2&gt;&#xA;&lt;p&gt;The signature of the functions in the &lt;code&gt;slices&lt;/code&gt; package is heavily influenced by the specifics of the representation of slices in memory. We recommend reading&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;/blog/slices-intro&#34;&gt;Go Slices: usage and internals&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;/blog/slices&#34;&gt;Arrays, slices: The mechanics of &amp;lsquo;append&amp;rsquo;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;The &lt;a href=&#34;https://en.wikipedia.org/wiki/Dynamic_array&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;dynamic array&lt;/a&gt; data structure&lt;/li&gt;&#xA;&lt;li&gt;The &lt;a href=&#34;/pkg/slices&#34;&gt;documentation&lt;/a&gt; of the package slices&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;/issue/63393&#34;&gt;original proposal&lt;/a&gt; about zeroing obsolete elements contains many details and comments.&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;Article prevnext&#34;&gt;&#xA;    &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;        &lt;p&gt;&#xA;        &#xA;          &#xA;            &lt;b&gt;Next article: &lt;/b&gt;&lt;a href=&#34;/blog/execution-traces-2024&#34;&gt;More powerful Go execution traces&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &#xA;          &#xA;            &lt;b&gt;Previous article: &lt;/b&gt;&lt;a href=&#34;/blog/routing-enhancements&#34;&gt;Routing Enhancements for Go 1.22&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &lt;b&gt;&lt;a href=&#34;/blog/all&#34;&gt;Blog Index&lt;/a&gt;&lt;/b&gt;&#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;    &lt;/div&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script src=&#34;/js/jquery.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/playground.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/play.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/godocs.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;</content></entry><entry><title>Routing Enhancements for Go 1.22</title><id>tag:blog.golang.org,2013:blog.golang.org/routing-enhancements</id><link rel="alternate" href="https://go.dev/blog/routing-enhancements"></link><published>2024-02-13T00:00:00+00:00</published><updated>2024-02-13T00:00:00+00:00</updated><author><name></name></author><summary type="html">Go 1.22&amp;#39;s additions to patterns for HTTP routes.</summary><content type="html">&#xA;&lt;div id=&#34;blog&#34;&gt;&lt;div id=&#34;content&#34;&gt;&#xA;  &lt;div id=&#34;content&#34;&gt;&#xA;&#xA;    &lt;div class=&#34;Article&#34; data-slug=&#34;/blog/routing-enhancements&#34;&gt;&#xA;    &#xA;    &lt;h1 class=&#34;small&#34;&gt;&lt;a href=&#34;/blog/&#34;&gt;The Go Blog&lt;/a&gt;&lt;/h1&gt;&#xA;    &#xA;&#xA;    &lt;h1&gt;Routing Enhancements for Go 1.22&lt;/h1&gt;&#xA;      &#xA;      &lt;p class=&#34;author&#34;&gt;&#xA;      Jonathan Amsterdam, on behalf of the Go team&lt;br&gt;&#xA;      13 February 2024&#xA;      &lt;/p&gt;&#xA;      &#xA;      &lt;p&gt;Go 1.22 brings two enhancements to the &lt;code&gt;net/http&lt;/code&gt; package&amp;rsquo;s router: method&#xA;matching and wildcards. These features let you express common routes as&#xA;patterns instead of Go code. Although they are simple to explain and use,&#xA;it was a challenge to come up with the right rules for selecting the winning&#xA;pattern when several match a request.&lt;/p&gt;&#xA;&lt;p&gt;We made these changes as part of our continuing effort to make Go a great&#xA;language for building production systems. We studied many third-party web&#xA;frameworks, extracted what we felt were the most used features, and integrated&#xA;them into &lt;code&gt;net/http&lt;/code&gt;. Then we validated our choices and improved our design by&#xA;collaborating with the community in a &lt;a href=&#34;https://github.com/golang/go/discussions/60227&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;GitHub discussion&lt;/a&gt; and a &lt;a href=&#34;/issue/61410&#34;&gt;proposal issue&lt;/a&gt;.&#xA;Adding these features to the standard library means one fewer dependency for&#xA;many projects. But third-party web frameworks remain a fine choice for current&#xA;users or programs with advanced routing needs.&lt;/p&gt;&#xA;&lt;h2 id=&#34;enhancements&#34;&gt;Enhancements&lt;/h2&gt;&#xA;&lt;p&gt;The new routing features almost exclusively affect the pattern string passed&#xA;to the two &lt;code&gt;net/http.ServeMux&lt;/code&gt; methods &lt;code&gt;Handle&lt;/code&gt; and &lt;code&gt;HandleFunc&lt;/code&gt;, and the&#xA;corresponding top-level functions &lt;code&gt;http.Handle&lt;/code&gt; and &lt;code&gt;http.HandleFunc&lt;/code&gt;. The only&#xA;API changes are two new methods on &lt;code&gt;net/http.Request&lt;/code&gt; for working with wildcard&#xA;matches.&lt;/p&gt;&#xA;&lt;p&gt;We&amp;rsquo;ll illustrate the changes with a hypothetical blog server in which every post&#xA;has an integer identifier. A request like &lt;code&gt;GET /posts/234&lt;/code&gt; retrieves the post with&#xA;ID 234. Before Go 1.22, the code for handling those requests would start with a&#xA;line like this:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;http.HandleFunc(&amp;quot;/posts/&amp;quot;, handlePost)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The trailing slash routes all requests beginning &lt;code&gt;/posts/&lt;/code&gt; to the &lt;code&gt;handlePost&lt;/code&gt;&#xA;function, which would have to check that the HTTP method was GET, extract&#xA;the identifier, and retrieve the post. Since the method check isn&amp;rsquo;t strictly&#xA;necessary to satisfy the request, it would be a natural mistake to omit it. That&#xA;would mean that a request like &lt;code&gt;DELETE /posts/234&lt;/code&gt; would fetch the post, which&#xA;is surprising at the least.&lt;/p&gt;&#xA;&lt;p&gt;In Go 1.22, the existing code will continue to work, or you could instead write this:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;http.HandleFunc(&amp;quot;GET /posts/{id}&amp;quot;, handlePost2)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;This pattern matches a GET request whose path begins &amp;ldquo;/posts/&amp;rdquo; and has two&#xA;segments. (As a special case, GET also matches HEAD; all the other methods match&#xA;exactly.) The &lt;code&gt;handlePost2&lt;/code&gt; function no longer needs to check the method, and&#xA;extracting the identifier string can be written using the new &lt;code&gt;PathValue&lt;/code&gt; method&#xA;on &lt;code&gt;Request&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;idString := req.PathValue(&amp;quot;id&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The rest of &lt;code&gt;handlePost2&lt;/code&gt; would behave like &lt;code&gt;handlePost&lt;/code&gt;, converting the string&#xA;identifier to an integer and fetching the post.&lt;/p&gt;&#xA;&lt;p&gt;Requests like &lt;code&gt;DELETE /posts/234&lt;/code&gt; will fail if no other matching pattern is&#xA;registered. In accordance with &lt;a href=&#34;https://httpwg.org/specs/rfc9110.html#status.405&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;HTTP semantics&lt;/a&gt;, a &lt;code&gt;net/http&lt;/code&gt; server will reply&#xA;to such a request with a &lt;code&gt;405 Method Not Allowed&lt;/code&gt; error that lists the available methods&#xA;in an &lt;code&gt;Allow&lt;/code&gt; header.&lt;/p&gt;&#xA;&lt;p&gt;A wildcard can match an entire segment, like &lt;code&gt;{id}&lt;/code&gt; in the example above, or if&#xA;it ends in &lt;code&gt;...&lt;/code&gt; it can match all the remaining segments of the path, as in the&#xA;pattern &lt;code&gt;/files/{pathname...}&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;There is one last bit of syntax. As we showed above, patterns ending in a slash,&#xA;like &lt;code&gt;/posts/&lt;/code&gt;, match all paths beginning with that string. To match only the&#xA;path with the trailing slash, you can write &lt;code&gt;/posts/{$}&lt;/code&gt;. That will match&#xA;&lt;code&gt;/posts/&lt;/code&gt; but not &lt;code&gt;/posts&lt;/code&gt; or &lt;code&gt;/posts/234&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;And there is one last bit of API: &lt;code&gt;net/http.Request&lt;/code&gt; has a &lt;code&gt;SetPathValue&lt;/code&gt; method&#xA;so that routers outside the standard library can make the results of their own&#xA;path parsing available via &lt;code&gt;Request.PathValue&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;precedence&#34;&gt;Precedence&lt;/h2&gt;&#xA;&lt;p&gt;Every HTTP router must deal with overlapping patterns, like &lt;code&gt;/posts/{id}&lt;/code&gt; and&#xA;&lt;code&gt;/posts/latest&lt;/code&gt;. Both of these patterns match the path &amp;ldquo;posts/latest&amp;rdquo;, but at most&#xA;one can serve the request. Which pattern takes precedence?&lt;/p&gt;&#xA;&lt;p&gt;Some routers disallow overlaps; others use the pattern that was registered last.&#xA;Go has always allowed overlaps, and has chosen the longer pattern regardless&#xA;of registration order. Preserving order-independence was important to us (and&#xA;necessary for backwards compatibility), but we needed a better rule than&#xA;&amp;ldquo;longest wins.&amp;rdquo; That rule would select &lt;code&gt;/posts/latest&lt;/code&gt; over &lt;code&gt;/posts/{id}&lt;/code&gt;, but&#xA;would choose &lt;code&gt;/posts/{identifier}&lt;/code&gt; over both. That seems wrong: the wildcard&#xA;name shouldn&amp;rsquo;t matter. It feels like &lt;code&gt;/posts/latest&lt;/code&gt; should always win this&#xA;competition, because it matches a single path instead of many.&lt;/p&gt;&#xA;&lt;p&gt;Our quest for a good precedence rule led us to consider many properties of&#xA;patterns. For example, we considered preferring the pattern with the longest&#xA;literal (non-wildcard) prefix. That would choose &lt;code&gt;/posts/latest&lt;/code&gt; over &lt;code&gt;/posts/ {id}&lt;/code&gt;. But it wouldn&amp;rsquo;t distinguish between &lt;code&gt;/users/{u}/posts/latest&lt;/code&gt; and&#xA;&lt;code&gt;/users/{u}/posts/{id}&lt;/code&gt;, and it seems like the former should take precedence.&lt;/p&gt;&#xA;&lt;p&gt;We eventually chose a rule based on what the patterns mean instead of how they&#xA;look. Every valid pattern matches a set of requests. For example,&#xA;&lt;code&gt;/posts/latest&lt;/code&gt; matches requests with the path &lt;code&gt;/posts/latest&lt;/code&gt;, while &lt;code&gt;/posts/{id}&lt;/code&gt;&#xA;matches requests with any two-segment path whose first segment is &amp;ldquo;posts&amp;rdquo;. We&#xA;say that one pattern is &lt;em&gt;more specific&lt;/em&gt; than another if it matches a strict subset&#xA;of requests. The pattern &lt;code&gt;/posts/latest&lt;/code&gt; is more specific than &lt;code&gt;/posts/{id}&lt;/code&gt;&#xA;because the latter matches every request that the former does, and more.&lt;/p&gt;&#xA;&lt;p&gt;The precedence rule is simple: the most specific pattern wins. This rule&#xA;matches our intuition that &lt;code&gt;posts/latests&lt;/code&gt; should be preferred to &lt;code&gt;posts/{id}&lt;/code&gt;,&#xA;and &lt;code&gt;/users/{u}/posts/latest&lt;/code&gt; should be preferred to &lt;code&gt;/users/{u}/posts/{id}&lt;/code&gt;.&#xA;It also makes sense for methods. For example, &lt;code&gt;GET /posts/{id}&lt;/code&gt; takes&#xA;precedence over &lt;code&gt;/posts/{id}&lt;/code&gt; because the first only matches GET and HEAD&#xA;requests, while the second matches requests with any method.&lt;/p&gt;&#xA;&lt;p&gt;The &amp;ldquo;most specific wins&amp;rdquo; rule generalizes the original &amp;ldquo;longest wins&amp;rdquo; rule for&#xA;the path parts of original patterns, those without wildcards or &lt;code&gt;{$}&lt;/code&gt;. Such&#xA;patterns only overlap when one is a prefix of the other, and the longer is the&#xA;more specific.&lt;/p&gt;&#xA;&lt;p&gt;What if two patterns overlap but neither is more specific? For example, &lt;code&gt;/posts/{id}&lt;/code&gt;&#xA;and &lt;code&gt;/{resource}/latest&lt;/code&gt; both match &lt;code&gt;/posts/latest&lt;/code&gt;. There is no obvious answer to&#xA;which takes precedence, so we consider these patterns to conflict with each other.&#xA;Registering both of them (in either order!) will panic.&lt;/p&gt;&#xA;&lt;p&gt;The precedence rule works exactly as above for methods and paths, but we had to&#xA;make one exception for hosts to preserve compatibility: if two patterns would&#xA;otherwise conflict and one has a host while the other does not, then the pattern&#xA;with the host takes precedence.&lt;/p&gt;&#xA;&lt;p&gt;Students of computer science may recall the beautiful theory of regular&#xA;expressions and regular languages. Each regular expression picks out a regular&#xA;language, the set of strings matched by the expression. Some questions are&#xA;easier to pose and answer by talking about languages rather than expressions.&#xA;Our precedence rule was inspired by this theory. Indeed, each routing pattern&#xA;corresponds to a regular expression, and sets of matching requests play the role of&#xA;regular languages.&lt;/p&gt;&#xA;&lt;p&gt;Defining precedence by languages instead of expressions makes it easy to state&#xA;and understand. But there is a downside to having a rule based on potentially&#xA;infinite sets: it isn&amp;rsquo;t clear how to implement it efficiently. It turns out we&#xA;can determine whether two patterns conflict by walking them segment by segment.&#xA;Roughly speaking, if one pattern has a literal segment wherever the other has a&#xA;wildcard, it is more specific; but if literals align with wildcards in both&#xA;directions, the patterns conflict.&lt;/p&gt;&#xA;&lt;p&gt;As new patterns are registered on a &lt;code&gt;ServeMux&lt;/code&gt;, it checks for conflicts with previously&#xA;registered patterns. But checking every pair of patterns would take quadratic&#xA;time. We use an index to skip patterns that cannot conflict with a new pattern;&#xA;in practice, it works quite well. In any case, this check happens when&#xA;patterns are registered, usually at server startup. The time to match incoming&#xA;requests in Go 1.22 hasn&amp;rsquo;t changed much from previous versions.&lt;/p&gt;&#xA;&lt;h2 id=&#34;compatibility&#34;&gt;Compatibility&lt;/h2&gt;&#xA;&lt;p&gt;We made every effort to keep the new functionality compatible with older&#xA;versions of Go. The new pattern syntax is a superset of the old, and the new&#xA;precedence rule generalizes the old one. But there are a few edge cases. For&#xA;example, previous versions of Go accepted patterns with braces and treated&#xA;them literally, but Go 1.22 uses braces for wildcards. The GODEBUG setting&#xA;&lt;code&gt;httpmuxgo121&lt;/code&gt; restores the old behavior.&lt;/p&gt;&#xA;&lt;p&gt;For more details about these routing enhancements, see the &lt;a href=&#34;/pkg/net/http#ServeMux&#34;&gt;&lt;code&gt;net/http.ServeMux&lt;/code&gt;&#xA;documentation&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;Article prevnext&#34;&gt;&#xA;    &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;        &lt;p&gt;&#xA;        &#xA;          &#xA;            &lt;b&gt;Next article: &lt;/b&gt;&lt;a href=&#34;/blog/generic-slice-functions&#34;&gt;Robust generic functions on slices&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &#xA;          &#xA;            &lt;b&gt;Previous article: &lt;/b&gt;&lt;a href=&#34;/blog/go1.22&#34;&gt;Go 1.22 is released!&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &lt;b&gt;&lt;a href=&#34;/blog/all&#34;&gt;Blog Index&lt;/a&gt;&lt;/b&gt;&#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;    &lt;/div&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script src=&#34;/js/jquery.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/playground.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/play.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/godocs.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;</content></entry><entry><title>Go 1.22 is released!</title><id>tag:blog.golang.org,2013:blog.golang.org/go1.22</id><link rel="alternate" href="https://go.dev/blog/go1.22"></link><published>2024-02-06T00:00:00+00:00</published><updated>2024-02-06T00:00:00+00:00</updated><author><name></name></author><summary type="html">Go 1.22 enhances for loops, brings new standard library functionality and improves performance.</summary><content type="html">&#xA;&lt;div id=&#34;blog&#34;&gt;&lt;div id=&#34;content&#34;&gt;&#xA;  &lt;div id=&#34;content&#34;&gt;&#xA;&#xA;    &lt;div class=&#34;Article&#34; data-slug=&#34;/blog/go1.22&#34;&gt;&#xA;    &#xA;    &lt;h1 class=&#34;small&#34;&gt;&lt;a href=&#34;/blog/&#34;&gt;The Go Blog&lt;/a&gt;&lt;/h1&gt;&#xA;    &#xA;&#xA;    &lt;h1&gt;Go 1.22 is released!&lt;/h1&gt;&#xA;      &#xA;      &lt;p class=&#34;author&#34;&gt;&#xA;      Eli Bendersky, on behalf of the Go team&lt;br&gt;&#xA;      6 February 2024&#xA;      &lt;/p&gt;&#xA;      &#xA;      &lt;p&gt;Today the Go team is thrilled to release Go 1.22,&#xA;which you can get by visiting the &lt;a href=&#34;/dl/&#34;&gt;download page&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Go 1.22 comes with several important new features and improvements. Here are&#xA;some of the notable changes; for the full list, refer to the &lt;a href=&#34;/doc/go1.22&#34;&gt;release&#xA;notes&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;language-changes&#34;&gt;Language changes&lt;/h2&gt;&#xA;&lt;p&gt;The long-standing &amp;ldquo;for&amp;rdquo; loop gotcha with accidental sharing of loop variables&#xA;between iterations is now resolved. Starting with Go 1.22, the following code&#xA;will print &amp;ldquo;a&amp;rdquo;, &amp;ldquo;b&amp;rdquo;, and &amp;ldquo;c&amp;rdquo; in some order:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;func main() {&#xA;    done := make(chan bool)&#xA;&#xA;    values := []string{&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;}&#xA;    for _, v := range values {&#xA;        go func() {&#xA;            fmt.Println(v)&#xA;            done &amp;lt;- true&#xA;        }()&#xA;    }&#xA;&#xA;    // wait for all goroutines to complete before exiting&#xA;    for _ = range values {&#xA;        &amp;lt;-done&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;For more information about this change and the tooling that helps keep code from&#xA;breaking accidentally, see the earlier &lt;a href=&#34;/blog/loopvar-preview&#34;&gt;loop variable blog&#xA;post&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The second language change is support for ranging over integers:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func main() {&#xA;    for i := range 10 {&#xA;        fmt.Println(10 - i)&#xA;    }&#xA;    fmt.Println(&amp;quot;go1.22 has lift-off!&amp;quot;)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The values of &lt;code&gt;i&lt;/code&gt; in this countdown program go from 0 to 9, inclusive. For more&#xA;details, please refer to &lt;a href=&#34;/ref/spec#For_range&#34;&gt;the spec&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;improved-performance&#34;&gt;Improved performance&lt;/h2&gt;&#xA;&lt;p&gt;Memory optimization in the Go runtime improves CPU performance by 1-3%, while&#xA;also reducing the memory overhead of most Go programs by around 1%.&lt;/p&gt;&#xA;&lt;p&gt;In Go 1.21, &lt;a href=&#34;/blog/pgo&#34;&gt;we shipped&lt;/a&gt; profile-guided optimization (PGO) for the Go&#xA;compiler and this functionality continues to improve. One of the optimizations&#xA;added in 1.22 is improved devirtualization, allowing static dispatch of more&#xA;interface method calls. Most programs will see improvements between 2-14% with&#xA;PGO enabled.&lt;/p&gt;&#xA;&lt;h2 id=&#34;standard-library-additions&#34;&gt;Standard library additions&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;A new &lt;a href=&#34;/pkg/math/rand/v2&#34;&gt;math/rand/v2&lt;/a&gt; package&#xA;provides a cleaner, more consistent API and uses higher-quality,&#xA;faster pseudo-random generation algorithms. See&#xA;&lt;a href=&#34;/issue/61716&#34;&gt;the proposal&lt;/a&gt; for additional details.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The patterns used by &lt;a href=&#34;/pkg/net/http#ServeMux&#34;&gt;net/http.ServeMux&lt;/a&gt;&#xA;now accept methods and wildcards.&lt;/p&gt;&#xA;&lt;p&gt;For example, the router accepts a pattern like &lt;code&gt;GET /task/{id}/&lt;/code&gt;, which&#xA;matches only &lt;code&gt;GET&lt;/code&gt; requests and captures the value of the &lt;code&gt;{id}&lt;/code&gt; segment&#xA;in a map that can be accessed through &lt;a href=&#34;/pkg/net/http#Request&#34;&gt;Request&lt;/a&gt; values.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;A new &lt;code&gt;Null[T]&lt;/code&gt; type in &lt;a href=&#34;/pkg/database/sql&#34;&gt;database/sql&lt;/a&gt; provides&#xA;a way to scan nullable columns.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;A &lt;code&gt;Concat&lt;/code&gt; function was added in package &lt;a href=&#34;/pkg/slices&#34;&gt;slices&lt;/a&gt;, to&#xA;concatenate multiple slices of any type.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Thanks to everyone who contributed to this release by writing code and&#xA;documentation, filing bugs, sharing feedback, and testing the release&#xA;candidates. Your efforts helped to ensure that Go 1.22 is as stable as possible.&#xA;As always, if you notice any problems, please &lt;a href=&#34;/issue/new&#34;&gt;file an issue&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Enjoy Go 1.22!&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;Article prevnext&#34;&gt;&#xA;    &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;        &lt;p&gt;&#xA;        &#xA;          &#xA;            &lt;b&gt;Next article: &lt;/b&gt;&lt;a href=&#34;/blog/routing-enhancements&#34;&gt;Routing Enhancements for Go 1.22&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &#xA;          &#xA;            &lt;b&gt;Previous article: &lt;/b&gt;&lt;a href=&#34;/blog/survey2024-h1&#34;&gt;Share your feedback about developing with Go&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &lt;b&gt;&lt;a href=&#34;/blog/all&#34;&gt;Blog Index&lt;/a&gt;&lt;/b&gt;&#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;    &lt;/div&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script src=&#34;/js/jquery.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/playground.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/play.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/godocs.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;</content></entry><entry><title>Share your feedback about developing with Go</title><id>tag:blog.golang.org,2013:blog.golang.org/survey2024-h1</id><link rel="alternate" href="https://go.dev/blog/survey2024-h1"></link><published>2024-01-23T00:00:00+00:00</published><updated>2024-01-23T00:00:00+00:00</updated><author><name></name></author><summary type="html">Help shape the future of Go by sharing your thoughts via the Go Developer Survey</summary><content type="html">&#xA;&lt;div id=&#34;blog&#34;&gt;&lt;div id=&#34;content&#34;&gt;&#xA;  &lt;div id=&#34;content&#34;&gt;&#xA;&#xA;    &lt;div class=&#34;Article&#34; data-slug=&#34;/blog/survey2024-h1&#34;&gt;&#xA;    &#xA;    &lt;h1 class=&#34;small&#34;&gt;&lt;a href=&#34;/blog/&#34;&gt;The Go Blog&lt;/a&gt;&lt;/h1&gt;&#xA;    &#xA;&#xA;    &lt;h1&gt;Share your feedback about developing with Go&lt;/h1&gt;&#xA;      &#xA;      &lt;p class=&#34;author&#34;&gt;&#xA;      Alice Merrick, for the Go team&lt;br&gt;&#xA;      23 January 2024&#xA;      &lt;/p&gt;&#xA;      &#xA;      &lt;p&gt;Happy New Year! &lt;a href=&#34;https://google.qualtrics.com/jfe/form/SV_083SVAUCji98YeO?s=b&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;The Go Developer Survey is now&#xA;open&lt;/a&gt;, and we want&#xA;to hear from you!&lt;/p&gt;&#xA;&lt;p&gt;Since 2016, the insights from our Go Developer Surveys have helped us identify&#xA;key usage patterns, understand developer challenges, discover tooling&#xA;preferences, and track emerging trends within the community. Your feedback is&#xA;essential in shaping the future of Go, so please take 10–15 minutes to complete&#xA;the survey by February 11, 2024. &lt;a href=&#34;https://google.qualtrics.com/jfe/form/SV_083SVAUCji98YeO?s=b&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Take the survey&#xA;now!&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;The more developers who participate, the better we&amp;rsquo;ll be able to understand the&#xA;needs of the Go community. You can help spread the word by sharing this survey&#xA;on your social media channels, with your co-workers, and in any other relevant&#xA;communities.&lt;/p&gt;&#xA;&lt;p&gt;Thank you for your time and feedback!&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;Article prevnext&#34;&gt;&#xA;    &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;        &lt;p&gt;&#xA;        &#xA;          &#xA;            &lt;b&gt;Next article: &lt;/b&gt;&lt;a href=&#34;/blog/go1.22&#34;&gt;Go 1.22 is released!&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &#xA;          &#xA;            &lt;b&gt;Previous article: &lt;/b&gt;&lt;a href=&#34;/blog/deadcode&#34;&gt;Finding unreachable functions with deadcode&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &lt;b&gt;&lt;a href=&#34;/blog/all&#34;&gt;Blog Index&lt;/a&gt;&lt;/b&gt;&#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;    &lt;/div&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script src=&#34;/js/jquery.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/playground.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/play.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/godocs.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;</content></entry><entry><title>Finding unreachable functions with deadcode</title><id>tag:blog.golang.org,2013:blog.golang.org/deadcode</id><link rel="alternate" href="https://go.dev/blog/deadcode"></link><published>2023-12-12T00:00:00+00:00</published><updated>2023-12-12T00:00:00+00:00</updated><author><name></name></author><summary type="html">deadcode is a new command to help identify functions that cannot be called.</summary><content type="html">&#xA;&lt;div id=&#34;blog&#34;&gt;&lt;div id=&#34;content&#34;&gt;&#xA;  &lt;div id=&#34;content&#34;&gt;&#xA;&#xA;    &lt;div class=&#34;Article&#34; data-slug=&#34;/blog/deadcode&#34;&gt;&#xA;    &#xA;    &lt;h1 class=&#34;small&#34;&gt;&lt;a href=&#34;/blog/&#34;&gt;The Go Blog&lt;/a&gt;&lt;/h1&gt;&#xA;    &#xA;&#xA;    &lt;h1&gt;Finding unreachable functions with deadcode&lt;/h1&gt;&#xA;      &#xA;      &lt;p class=&#34;author&#34;&gt;&#xA;      Alan Donovan&lt;br&gt;&#xA;      12 December 2023&#xA;      &lt;/p&gt;&#xA;      &#xA;      &lt;p&gt;Functions that are part of your project&amp;rsquo;s source code but can never be&#xA;reached in any execution are called &amp;ldquo;dead code&amp;rdquo;, and they exert a drag&#xA;on codebase maintenance efforts.&#xA;Today we&amp;rsquo;re pleased to share a tool named &lt;code&gt;deadcode&lt;/code&gt; to help you identify them.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;$ go install golang.org/x/tools/cmd/deadcode@latest&#xA;$ deadcode -help&#xA;The deadcode command reports unreachable functions in Go programs.&#xA;&#xA;Usage: deadcode [flags] package...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;&#xA;&lt;p&gt;Over the last year or so, we&amp;rsquo;ve been making a lot of changes to the&#xA;structure of &lt;a href=&#34;/blog/gopls-scalability&#34;&gt;gopls&lt;/a&gt;, the&#xA;language server for Go that powers VS Code and other editors.&#xA;A typical change might rewrite some existing function, taking care to&#xA;ensure that its new behavior satisfies the needs of all existing callers.&#xA;Sometimes, after putting in all that effort, we would discover to our&#xA;frustration that one of the callers was never actually reached in any&#xA;execution, so it could safely have been been deleted.&#xA;If we had known this beforehand our refactoring task would have been&#xA;easier.&lt;/p&gt;&#xA;&lt;p&gt;The simple Go program below illustrates the problem:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;module example.com/greet&#xA;go 1.21&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func main() {&#xA;    var g Greeter&#xA;    g = Helloer{}&#xA;    g.Greet()&#xA;}&#xA;&#xA;type Greeter interface{ Greet() }&#xA;&#xA;type Helloer struct{}&#xA;type Goodbyer struct{}&#xA;&#xA;var _ Greeter = Helloer{}  // Helloer  implements Greeter&#xA;var _ Greeter = Goodbyer{} // Goodbyer implements Greeter&#xA;&#xA;func (Helloer) Greet()  { hello() }&#xA;func (Goodbyer) Greet() { goodbye() }&#xA;&#xA;func hello()   { fmt.Println(&amp;quot;hello&amp;quot;) }&#xA;func goodbye() { fmt.Println(&amp;quot;goodbye&amp;quot;) }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;When we execute it, it says hello:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;$ go run .&#xA;hello&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;It&amp;rsquo;s clear from its output that this program executes the &lt;code&gt;hello&lt;/code&gt;&#xA;function but not the &lt;code&gt;goodbye&lt;/code&gt; function.&#xA;What&amp;rsquo;s less clear at a glance is that the &lt;code&gt;goodbye&lt;/code&gt; function can&#xA;never be called.&#xA;However, we can&amp;rsquo;t simply delete &lt;code&gt;goodbye&lt;/code&gt;, because it&amp;rsquo;s required by the&#xA;&lt;code&gt;Goodbyer.Greet&lt;/code&gt; method, which in turn is required to implement the&#xA;&lt;code&gt;Greeter&lt;/code&gt; interface whose &lt;code&gt;Greet&lt;/code&gt; method we can see is called from &lt;code&gt;main&lt;/code&gt;.&#xA;But if we work forwards from main, we can see that no &lt;code&gt;Goodbyer&lt;/code&gt; values&#xA;are ever created, so the &lt;code&gt;Greet&lt;/code&gt; call in &lt;code&gt;main&lt;/code&gt; can only reach &lt;code&gt;Helloer.Greet&lt;/code&gt;.&#xA;That&amp;rsquo;s the idea behind the algorithm used by the &lt;code&gt;deadcode&lt;/code&gt; tool.&lt;/p&gt;&#xA;&lt;p&gt;When we run deadcode on this program, the tool tells us that the&#xA;&lt;code&gt;goodbye&lt;/code&gt; function and the &lt;code&gt;Goodbyer.Greet&lt;/code&gt; method are both unreachable:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;$ deadcode .&#xA;greet.go:23: unreachable func: goodbye&#xA;greet.go:20: unreachable func: Goodbyer.Greet&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;With this knowledge, we can safely remove both functions,&#xA;along with the &lt;code&gt;Goodbyer&lt;/code&gt; type itself.&lt;/p&gt;&#xA;&lt;p&gt;The tool can also explain why the &lt;code&gt;hello&lt;/code&gt; function is live. It responds&#xA;with a chain of function calls that reaches &lt;code&gt;hello&lt;/code&gt;, starting from main:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;$ deadcode -whylive=example.com/greet.hello .&#xA;                  example.com/greet.main&#xA;dynamic@L0008 --&amp;gt; example.com/greet.Helloer.Greet&#xA; static@L0019 --&amp;gt; example.com/greet.hello&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The output is designed to be easy to read on a terminal, but you can&#xA;use the &lt;code&gt;-json&lt;/code&gt; or &lt;code&gt;-f=template&lt;/code&gt; flags to specify richer output formats for&#xA;consumption by other tools.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-it-works&#34;&gt;How it works&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;code&gt;deadcode&lt;/code&gt; command&#xA;&lt;a href=&#34;https://pkg.go.dev/golang.org/x/tools/go/packages&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;loads&lt;/a&gt;,&#xA;&lt;a href=&#34;https://pkg.go.dev/go/parser&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;parses&lt;/a&gt;,&#xA;and &lt;a href=&#34;https://pkg.go.dev/go/types&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;type-checks&lt;/a&gt; the specified packages,&#xA;then converts them into an&#xA;&lt;a href=&#34;https://pkg.go.dev/golang.org/x/tools/go/ssa&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;intermediate representation&lt;/a&gt;&#xA;similar to a typical compiler.&lt;/p&gt;&#xA;&lt;p&gt;It then uses an algorithm called&#xA;&lt;a href=&#34;https://pkg.go.dev/golang.org/x/tools/go/callgraph/rta&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Rapid Type Analysis&lt;/a&gt; (RTA)&#xA;to build up the set of functions that are reachable,&#xA;which is initially just the entry points of each &lt;code&gt;main&lt;/code&gt; package:&#xA;the &lt;code&gt;main&lt;/code&gt; function,&#xA;and the package initializer function,&#xA;which assigns global variables and calls functions named &lt;code&gt;init&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;RTA looks at the statements in the body of each reachable function to&#xA;gather three kinds of information: the set of functions it calls directly;&#xA;the set of dynamic calls it makes through interface methods;&#xA;and the set of types it converts to an interface.&lt;/p&gt;&#xA;&lt;p&gt;Direct function calls are easy: we just add the callee to the set of&#xA;reachable functions, and if it&amp;rsquo;s the first time we&amp;rsquo;ve encountered the&#xA;callee, we inspect its function body the same way we did for main.&lt;/p&gt;&#xA;&lt;p&gt;Dynamic calls through interface methods are trickier, because we don&amp;rsquo;t&#xA;know the set of types that implement the interface. We don&amp;rsquo;t want&#xA;to assume that every possible method in the program whose type matches&#xA;is a possible target for the call, because some of those types may&#xA;be instantiated only from dead code! That&amp;rsquo;s why we gather the set of&#xA;types converted to interfaces: the conversion makes each of these&#xA;types reachable from &lt;code&gt;main&lt;/code&gt;, so that its methods are now possible&#xA;targets of dynamic calls.&lt;/p&gt;&#xA;&lt;p&gt;This leads to a chicken-and-egg situation. As we encounter each new&#xA;reachable function, we discover more interface method calls and more&#xA;conversions of concrete types to interface types.&#xA;But as the cross product of these two sets (interface method calls ×&#xA;concrete types) grows ever larger, we discover new reachable&#xA;functions.&#xA;This class of problems, called &amp;ldquo;dynamic programming&amp;rdquo;, can be solved by&#xA;(conceptually) making checkmarks in a large two-dimensional table,&#xA;adding rows and columns as we go, until there are no more checks to&#xA;add. The checkmarks in the final table tells us what is reachable;&#xA;the blank cells are the dead code.&lt;/p&gt;&#xA;&lt;div class=&#34;image&#34;&gt;&#xA;&lt;center&gt;&#xA;  &lt;img src=&#34;deadcode-rta.svg&#34; alt=&#34;illustration of Rapid Type Analysis&#34;/&gt;&lt;br/&gt;  &lt;i&gt;&#xA;   The &lt;code&gt;main&lt;/code&gt; function causes &lt;code&gt;Helloer&lt;/code&gt; to be&#xA;   instantiated, and the &lt;code&gt;g.Greet&lt;/code&gt; call&lt;br/&gt;&#xA;   dispatches to the &lt;code&gt;Greet&lt;/code&gt; method of each type instantiated so far.&#xA;  &lt;/i&gt;&#xA;&lt;/center&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;Dynamic calls to (non-method) functions are treated similar to&#xA;interfaces of a single method.&#xA;And calls made &lt;a href=&#34;https://pkg.go.dev/reflect#Value.Call&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;using reflection&lt;/a&gt;&#xA;are considered to reach any method of any type used in an interface&#xA;conversion, or any type derivable from one using the &lt;code&gt;reflect&lt;/code&gt; package.&#xA;But the principle is the same in all cases.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tests&#34;&gt;Tests&lt;/h2&gt;&#xA;&lt;p&gt;RTA is a whole-program analysis. That means it always starts from a&#xA;main function and works forward: you can&amp;rsquo;t start from a library&#xA;package such as &lt;code&gt;encoding/json&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;However, most library packages have tests, and tests have main&#xA;functions. We don&amp;rsquo;t see them because they are generated behind the&#xA;scenes of &lt;code&gt;go test&lt;/code&gt;, but we can include them in the analysis using the&#xA;&lt;code&gt;-test&lt;/code&gt; flag.&lt;/p&gt;&#xA;&lt;p&gt;If this reports that a function in a library package is dead, that&amp;rsquo;s&#xA;a sign that your test coverage could be improved.&#xA;For example, this command lists all the functions in &lt;code&gt;encoding/json&lt;/code&gt;&#xA;that are not reached by any of its tests:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;$ deadcode -test -filter=encoding/json encoding/json&#xA;encoding/json/decode.go:150:31: unreachable func: UnmarshalFieldError.Error&#xA;encoding/json/encode.go:225:28: unreachable func: InvalidUTF8Error.Error&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;(The &lt;code&gt;-filter&lt;/code&gt; flag restricts the output to packages matching the&#xA;regular expression. By default, the tool reports all packages in the&#xA;initial module.)&lt;/p&gt;&#xA;&lt;h2 id=&#34;soundness&#34;&gt;Soundness&lt;/h2&gt;&#xA;&lt;p&gt;All static analysis tools&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Rice%27s_theorem&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;necessarily&lt;/a&gt;&#xA;produce imperfect approximations of the possible dynamic&#xA;behaviors of the target program.&#xA;A tool&amp;rsquo;s assumptions and inferences may be &amp;ldquo;sound&amp;rdquo;, meaning&#xA;conservative but perhaps overly cautious, or &amp;ldquo;unsound&amp;rdquo;, meaning&#xA;optimistic but not always correct.&lt;/p&gt;&#xA;&lt;p&gt;The deadcode tool is no exception: it must approximate the set of&#xA;targets of dynamic calls through function and interface values or&#xA;using reflection.&#xA;In this respect, the tool is sound. In other words, if it reports a&#xA;function as dead code, it means the function cannot be called even&#xA;through these dynamic mechanisms. However the tool may fail to report&#xA;some functions that in fact can never be executed.&lt;/p&gt;&#xA;&lt;p&gt;The deadcode tool must also approximate the set of calls made from&#xA;functions not written in Go, which it cannot see.&#xA;In this respect, the tool is not sound.&#xA;Its analysis is not aware of functions called exclusively from&#xA;assembly code, or of the aliasing of functions that arises from&#xA;the &lt;a href=&#34;https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;go:linkname&lt;/code&gt; directive&lt;/a&gt;.&#xA;Fortunately both of these features are rarely used outside the Go runtime.&lt;/p&gt;&#xA;&lt;h2 id=&#34;try-it-out&#34;&gt;Try it out&lt;/h2&gt;&#xA;&lt;p&gt;We run &lt;code&gt;deadcode&lt;/code&gt; periodically on our projects, especially after&#xA;refactoring work, to help identify parts of the program that are no&#xA;longer needed.&lt;/p&gt;&#xA;&lt;p&gt;With the dead code laid to rest, you can focus on eliminating code&#xA;whose time has come to an end but that stubbornly remains alive,&#xA;continuing to drain your life force. We call such undead functions&#xA;&amp;ldquo;vampire code&amp;rdquo;!&lt;/p&gt;&#xA;&lt;p&gt;Please try it out:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;$ go install golang.org/x/tools/cmd/deadcode@latest&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;We&amp;rsquo;ve found it useful, and we hope you do too.&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;Article prevnext&#34;&gt;&#xA;    &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;        &lt;p&gt;&#xA;        &#xA;          &#xA;            &lt;b&gt;Next article: &lt;/b&gt;&lt;a href=&#34;/blog/survey2024-h1&#34;&gt;Share your feedback about developing with Go&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &#xA;          &#xA;            &lt;b&gt;Previous article: &lt;/b&gt;&lt;a href=&#34;/blog/survey2023-h2-results&#34;&gt;Go Developer Survey 2023 H2 Results&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &lt;b&gt;&lt;a href=&#34;/blog/all&#34;&gt;Blog Index&lt;/a&gt;&lt;/b&gt;&#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;    &lt;/div&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script src=&#34;/js/jquery.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/playground.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/play.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/godocs.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;</content></entry><entry><title>Go Developer Survey 2023 H2 Results</title><id>tag:blog.golang.org,2013:blog.golang.org/survey2023-h2-results</id><link rel="alternate" href="https://go.dev/blog/survey2023-h2-results"></link><published>2023-12-05T00:00:00+00:00</published><updated>2023-12-05T00:00:00+00:00</updated><author><name></name></author><summary type="html">What we learned from our 2023 H2 developer survey</summary><content type="html">&#xA;&lt;div id=&#34;blog&#34;&gt;&lt;div id=&#34;content&#34;&gt;&#xA;  &lt;div id=&#34;content&#34;&gt;&#xA;&#xA;    &lt;div class=&#34;Article&#34; data-slug=&#34;/blog/survey2023-h2-results&#34;&gt;&#xA;    &#xA;    &lt;h1 class=&#34;small&#34;&gt;&lt;a href=&#34;/blog/&#34;&gt;The Go Blog&lt;/a&gt;&lt;/h1&gt;&#xA;    &#xA;&#xA;    &lt;h1&gt;Go Developer Survey 2023 H2 Results&lt;/h1&gt;&#xA;      &#xA;      &lt;p class=&#34;author&#34;&gt;&#xA;      Todd Kulesza&lt;br&gt;&#xA;      5 December 2023&#xA;      &lt;/p&gt;&#xA;      &#xA;      &lt;style type=&#34;text/css&#34; scoped&gt;&#xA;  .chart {&#xA;    margin-left: 1.5rem;&#xA;    margin-right: 1.5rem;&#xA;    width: 800px;&#xA;  }&#xA;  blockquote p {&#xA;    color: var(--color-text-subtle) !important;&#xA;  }&#xA;&#xA;  .quote_source {&#xA;    font-style: italic;&#xA;  }&#xA;&#xA;  @media (prefers-color-scheme: dark) {&#xA;    .chart {&#xA;      border-radius: 8px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;&#xA;&lt;p&gt;In August 2023, the Go team at Google conducted our bi-annual survey of Go&#xA;developers. We recruited participants via a public post on the Go blog and a&#xA;randomized prompt in VS Code, resulting in 4,005 responses. We primarily&#xA;focused survey questions around a few topics: general sentiment and feedback&#xA;about developing with Go, technology stacks used alongside Go, how developers&#xA;start new Go projects, recent experiences with toolchain error messages, and&#xA;understanding developer interest around ML/AI.&lt;/p&gt;&#xA;&lt;p&gt;Thank you to everyone who participated in this survey! This report shares what&#xA;we learned from your feedback.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tldr&#34;&gt;tl;dr&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Go developers said they are &lt;strong&gt;more interested in AI/ML tooling that&#xA;improves the quality, reliability, and performance of code they write&lt;/strong&gt;,&#xA;rather than writing code for them. An always-awake, never-busy expert&#xA;&amp;ldquo;reviewer&amp;rdquo; might be one of the more helpful forms of AI developer&#xA;assistance.&lt;/li&gt;&#xA;&lt;li&gt;The top requests for improving toolchain warnings and errors were to &lt;strong&gt;make&#xA;the messages more comprehensible and actionable&lt;/strong&gt;; this sentiment was&#xA;shared by developers of all experience levels, but was particularly strong&#xA;among newer Go developers.&lt;/li&gt;&#xA;&lt;li&gt;Our experiment with project templates (&lt;code&gt;gonew&lt;/code&gt;) appears to solve critical&#xA;problems for Go developers (especially developers new to Go) and does so in&#xA;a way that matches their existing workflows for starting a new project.&#xA;Based on these findings, we believe &lt;strong&gt;&lt;code&gt;gonew&lt;/code&gt; can substantially reduce&#xA;onboarding barriers for new Go developers and ease adoption of Go in&#xA;organizations&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Three out of every four respondents work on Go software that also uses&#xA;cloud services; this is evidence that &lt;strong&gt;developers see Go as a language for&#xA;modern, cloud-based development&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Developer sentiment towards Go remains extremely positive&lt;/strong&gt;, with 90% of&#xA;survey respondents saying they felt satisfied while working with Go during&#xA;the prior year.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;contents&#34;&gt;Contents&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#sentiment&#34;&gt;Developer sentiment&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#devenv&#34;&gt;Developer environments&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#stacks&#34;&gt;Tech stacks&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#gonew&#34;&gt;How developers start new Go projects&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#err_handling&#34;&gt;Developer goals for error handling&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#mlai&#34;&gt;Understanding ML/AI use cases&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#err_msgs&#34;&gt;Toolchain error messages&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#microservices&#34;&gt;Microservices&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#modules&#34;&gt;Module authorship and maintenance&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#demographics&#34;&gt;Demographics&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#firmographics&#34;&gt;Firmographics&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#methodology&#34;&gt;Methodology&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#closing&#34;&gt;Closing&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;sentiment&#34;&gt;Developer sentiment&lt;/h2&gt;&#xA;&lt;p&gt;Go developers continue to report high levels of satisfaction with the Go&#xA;ecosystem. A large majority of respondents said they felt satisfied while&#xA;working with Go over the past year (90% satisfied, 6% dissatisfied), and a&#xA;majority (52%) went further and said they were &amp;ldquo;very satisfied&amp;rdquo;, the highest&#xA;rating. Longtime readers have likely noticed that this number doesn&amp;rsquo;t change&#xA;much from year to year. This is expected for a large, stable project like Go;&#xA;we view this metric as a &lt;a href=&#34;https://en.wikipedia.org/wiki/Economic_indicator#Lagging_indicators&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;lagging&#xA;indicator&lt;/a&gt;&#xA;that can help confirm widespread issues in the Go ecosystem, but isn&amp;rsquo;t where&#xA;we expect to first learn about potential problems.&lt;/p&gt;&#xA;&lt;p&gt;We typically find that the longer someone has worked with Go, the more likely&#xA;they are to report being satisfied with it. This trend continued in 2023;&#xA;among respondents with less than one year of Go experience, 82% reported&#xA;satisfaction with the Go development experience, compared to the 94% of Go&#xA;developers with five or more years of experience. There are likely a mix of&#xA;factors contributing to this, such as some respondents developing an&#xA;appreciation for Go&amp;rsquo;s design choices over time, or deciding Go isn&amp;rsquo;t a good&#xA;fit for their work and so not returning to this survey in following years&#xA;(i.e., &lt;a href=&#34;https://en.wikipedia.org/wiki/Survivorship_bias&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;survivorship bias&lt;/a&gt;).&#xA;Still, this data helps us quantify the current getting started experience for&#xA;Go developers, and it seems clear we could do more to help emerging Gophers&#xA;find their footing and enjoy early successes developing with Go.&lt;/p&gt;&#xA;&lt;p&gt;The key takeaway is that a large majority of people who chose to work with Go&#xA;during the past year were happy with their experience. Further, the number of&#xA;people working with Go continues to increase; we see evidence of this from&#xA;external research like &lt;a href=&#34;https://survey.stackoverflow.co/2023/#most-popular-technologies-language-prof&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Stack Overflow&amp;rsquo;s Developer&#xA;Survey&lt;/a&gt;&#xA;(which found 14% of professional developers worked with Go during the past&#xA;year, a roughly 15% year-over-year increase), as well as analytics for&#xA;&lt;a href=&#34;/&#34;&gt;go.dev&lt;/a&gt; (which show an 8% rise in visitors year-over-year).&#xA;Combining this growth with a high satisfaction score is evidence that Go&#xA;continues to appeal to developers, and suggests that many developers who&#xA;choose to learn the language feel good about their decision long afterwards.&#xA;In their own words:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;After 30+ years of development in C, C++, Java, and now seven years of&#xA;programming in Go, it is still the most productive language by far. It&amp;rsquo;s not&#xA;perfect (no language is), but it has the best balance of productivity,&#xA;complexity, and performance.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go&#xA;developer w/ 5 &amp;ndash; 9 years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;This is currently the best language I know, and I&amp;rsquo;ve tried many. The&#xA;tooling is awesome, compile times are great, and I can be really productive.&#xA;I&amp;rsquo;m glad I have Go as a tool, and I don&amp;rsquo;t need to use TypeScript&#xA;server-side. Thanks.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Open source Go&#xA;developer w/ 3 &amp;ndash; 4 years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/csat.svg&#34; alt=&#34;Chart of developer satisfaction with Go&#34;&#xA;class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;devenv&#34;&gt;Developer environments&lt;/h2&gt;&#xA;&lt;p&gt;As in prior years, the majority of survey respondents told us they work with&#xA;Go on Linux (63%) and macOS (58%) systems. Small variations in these numbers&#xA;from year to year are most likely dependent upon who finds and responds to&#xA;this survey (particularly on the Go blog), as we don&amp;rsquo;t see consistent&#xA;year-over-year trends in the random sample coming from VS Code.&lt;/p&gt;&#xA;&lt;p&gt;We do continue to see that newer members of the Go community are more likely&#xA;to be working with Windows than more experienced Go developers. We interpret&#xA;this as a signal that Windows-based development is important for onboarding&#xA;new developers to the Go ecosystem, and is a topic our team hopes to focus on&#xA;more in 2024.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/os_dev.svg&#34; alt=&#34;Chart of operating systems respondents&#xA;use when developing Go software&#34; class=&#34;chart&#34; /&gt; &lt;img&#xA;src=&#34;survey2023h2/os_dev_exp.svg&#34; alt=&#34;Chart of operating systems respondents&#xA;use when developing Go software, split by duration of experience&#34;&#xA;class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Respondents continue to be heavily focused on Linux deployments. Given the&#xA;prevalence of Go for cloud development and containerized workloads, this is&#xA;not surprising but is still an important confirmation. We found few meaningful&#xA;differences based on factors such as organization size or experience level;&#xA;indeed, while novice Go developers appear more likely to &lt;em&gt;develop&lt;/em&gt; on Windows,&#xA;92% still &lt;em&gt;deploy&lt;/em&gt; to Linux systems. Perhaps the most interesting finding from&#xA;this breakdown is that more experienced Go developers said they deploy to a&#xA;wider variety of systems (most notably WebAssembly and IoT), though it&amp;rsquo;s&#xA;unclear if this is because such deployments are challenging for newer Go&#xA;developers or the result of experienced Go developers using Go in a broader&#xA;range of contexts. We also observed that both IoT and WebAssembly have&#xA;steadily increased in recent years, with each rising from 3% in 2021 to 6% and&#xA;5% in 2023, respectively.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/os_deploy.svg&#34; alt=&#34;Chart of platforms respondents&#xA;deploy Go software to&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;The computing architecture landscape has changed over the past few years, and&#xA;we see that reflected in the current architectures Go developers say they work&#xA;with. While x86-compatible systems still account for the majority of&#xA;development (89%), ARM64 is also now used by a majority of respondents (56%).&#xA;This adoption appears to be partly driven by Apple Silicon; macOS developers&#xA;are now more likely to say they develop for ARM64 than for x86-based&#xA;architectures (76% vs. 71%). However, Apple hardware isn&amp;rsquo;t the only factor&#xA;driving ARM64 adoption: among respondents who don&amp;rsquo;t develop on macOS at all,&#xA;29% still say they develop for ARM64.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/arch.svg&#34; alt=&#34;Chart of architectures respondents use&#xA;with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;The most common code editors among Go Developer Survey respondents continue to&#xA;be &lt;a href=&#34;https://code.visualstudio.com/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;VS Code&lt;/a&gt; (44%) and&#xA;&lt;a href=&#34;https://www.jetbrains.com/go/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;GoLand&lt;/a&gt; (31%). Both of these proportions&#xA;ticked down slightly from 2023 H1 (46% and 33%, respectively), but remain&#xA;within this survey&amp;rsquo;s margin of error. Among the &amp;ldquo;Other&amp;rdquo; category,&#xA;&lt;a href=&#34;https://helix-editor.com/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;Helix&lt;/a&gt; accounted for the majority of responses.&#xA;Similar to the results for operating systems above, we don&amp;rsquo;t believe this&#xA;represents a meaningful shift in code editor usage, but rather shows some of&#xA;the variability we expect to see in a community survey such as this. In&#xA;particular, we exclude the randomly sampled respondents from VS Code for this&#xA;question, as we know that group is heavily biased towards VS Code. However,&#xA;that has the side effect of making these results more susceptible to variation&#xA;each year.&lt;/p&gt;&#xA;&lt;p&gt;We also looked at respondents&amp;rsquo; level of satisfaction with Go based on the&#xA;editor they prefer using. After controlling for length of experience, we found&#xA;no differences: we don&amp;rsquo;t believe people enjoy working with Go more or less&#xA;based on which code editor they use. That doesn&amp;rsquo;t necessarily mean all Go&#xA;editors are equal, but may reflect that people find the editor that is best&#xA;for their own needs. This would suggest the Go ecosystem has a healthy&#xA;diversity of different editors geared towards different use cases and&#xA;developer preferences.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/editor_self_select.svg&#34; alt=&#34;Chart of code editors&#xA;respondents prefer to use with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;stacks&#34;&gt;Tech stacks&lt;/h2&gt;&#xA;&lt;p&gt;To better understand the web of software and services that Go developers&#xA;interact with, we asked several questions about tech stacks. We&amp;rsquo;re sharing&#xA;these results with the community to show which tools and platforms are in&#xA;common use today, but we believe everyone should consider their own needs and&#xA;use cases when selecting a tech stack. More plainly: we neither intend for&#xA;readers to use this data to select components of their tech stack because they&#xA;are popular, nor to avoid components because they are not commonly used.&lt;/p&gt;&#xA;&lt;p&gt;First, we can say with confidence that Go is a language for modern cloud-based&#xA;development. Indeed, 75% of respondents work on Go software that integrates&#xA;with cloud services. For nearly half of respondents, this involved AWS (48%),&#xA;and almost one-third used GCP (29%) for their Go development and deployments.&#xA;For both AWS and GCP, usage is equally balanced among large enterprises and&#xA;smaller organizations. Microsoft Azure is the only cloud provider that is&#xA;significantly more likely to be used in large organizations (companies with &amp;gt;&#xA;1,000 employees) than smaller shops; other providers show no meaningful&#xA;differences in usage based on the size of the organization.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/cloud.svg&#34; alt=&#34;Chart of cloud platforms respondents&#xA;use with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Databases are extremely common components of software systems, and we found&#xA;that 91% of respondents said the Go services they work on use at least one.&#xA;Most frequently this was PostgreSQL (59%), but with double digits of&#xA;respondents reporting use of six additional databases, it&amp;rsquo;s safe to say there&#xA;are not just a couple of standard DBs for Go developers to consider. We again&#xA;see differences based on organization size, with respondents from smaller&#xA;organizations more likely to report using PostgreSQL and Redis, while&#xA;developers from large organizations are somewhat more likely to use a database&#xA;specific to their cloud provider.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/db.svg&#34; alt=&#34;Chart of databases respondents use with&#xA;Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Another common component respondents reported using were caches or key-value&#xA;stores; 68% of respondents said they work on Go software incorporating at&#xA;least one of these. Redis was clearly the most common (57%), followed at a&#xA;distance by etcd (10%) and memcached (7%).&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/cache.svg&#34; alt=&#34;Chart of caches respondents use with&#xA;Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Similar to databases, survey respondents told us they use a range of different&#xA;observability systems. Prometheus and Grafana were the most commonly cited&#xA;(both at 43%), but Open Telemetry, Datadog, and Sentry were all in double&#xA;digits.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/metrics.svg&#34; alt=&#34;Chart of metric systems respondents&#xA;use with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Lest anyone wonder &amp;ldquo;Have we JSON&amp;rsquo;d all the things?&amp;rdquo;&amp;hellip; yes, yes we have.&#xA;Nearly every respondent (96%!) said their Go software uses the JSON data&#xA;format; that&amp;rsquo;s about as close to universal as you&amp;rsquo;ll see with self-reported&#xA;data. YAML, CSV, and protocol buffers are also all used by roughly half of&#xA;respondents, and double-digit proportions work with TOML and XML as well.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/data.svg&#34; alt=&#34;Chart of data formats respondents use&#xA;with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;For authentication and authorization services, we found most respondents are&#xA;building upon the foundations provided by standards such as&#xA;&lt;a href=&#34;https://jwt.io/introduction&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;JWT&lt;/a&gt; and &lt;a href=&#34;https://oauth.net/2/&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;OAuth2&lt;/a&gt;. This&#xA;also appears to be an area where an organization&amp;rsquo;s cloud provider&amp;rsquo;s solution&#xA;is about as likely to be used as most turn-key alternatives.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/auth.svg&#34; alt=&#34;Chart of authentication systems&#xA;respondents use with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Finally, we have a bit of a grab bag of other services that don&amp;rsquo;t neatly fit&#xA;into the above categories. We found that nearly half of respondents work with&#xA;gRPC in their Go software (47%). For infrastructure-as-code needs, Terraform&#xA;was the tool of choice for about ¼ of respondents. Other fairly common&#xA;technologies used alongside Go included Apache Kafka, ElasticSearch, GraphQL,&#xA;and RabbitMQ.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/other_tech.svg&#34; alt=&#34;Chart of authentication systems&#xA;respondents use with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;We also looked at which technologies tended to be used together. While nothing&#xA;clearly analogous to the classic &lt;a href=&#34;https://en.wikipedia.org/wiki/LAMP_(software_bundle)&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;LAMP&#xA;stack&lt;/a&gt; emerged from this&#xA;analysis, we did identify some interesting patterns:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;All or nothing: Every category (except data formats) showed a strong&#xA;correlation where if a respondent answered “None” to one category, they&#xA;likely answered “None” for all of the others. We interpret this as evidence&#xA;that a minority of use cases require none of these tech stack components,&#xA;but once the use case requires any one of them, it likely requires (or is at&#xA;least simplified by) more than just one.&lt;/li&gt;&#xA;&lt;li&gt;A bias towards cross-platform technologies: Provider-specific solutions&#xA;(i.e., services that are unique to a single cloud platform) were not&#xA;commonly adopted. However, if respondents used one provider-specific&#xA;solution (e.g., for metrics), they were substantially more likely to also&#xA;say they used cloud-specific solutions in order areas (e.g., databases,&#xA;authentication, caching, etc.).&lt;/li&gt;&#xA;&lt;li&gt;Multicloud: The three biggest cloud platforms were most likely to be&#xA;involved in multicloud setups. For example, if an organization is using any&#xA;non-AWS cloud provider, they’re probably also using AWS. This pattern was&#xA;clearest for Amazon Web Services, but was also apparent (to a lesser extent)&#xA;for Google Cloud Platform and Microsoft Azure.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;gonew&#34;&gt;How developers start new Go projects&lt;/h2&gt;&#xA;&lt;p&gt;As part of our &lt;a href=&#34;/blog/gonew&#34;&gt;experimentation with project&#xA;templates&lt;/a&gt;, we wanted to understand how Go&#xA;developers get started with new projects today. Respondents told us their&#xA;biggest challenges were choosing an appropriate way to structure their project&#xA;(54%) and learning how to write idiomatic Go (47%). As two respondents phrased&#xA;it:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Finding an appropriate structure and the right abstraction levels for a new&#xA;project can be quite tedious; looking at high-profile community and&#xA;enterprise projects for inspiration can be quite confusing as everyone&#xA;structures their project differently&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash;&#xA;Professional Go developer w/ 5 &amp;ndash; 9 years of Go experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;It would be great if [Go had a] toolchain to create [a project&amp;rsquo;s] basic&#xA;structure for web or CLI like `go init &amp;lt;project name&amp;gt;`&amp;rdquo; &lt;span&#xA;class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer w/ 3 &amp;ndash; 4 years of&#xA;experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Newer Go developers were even more likely to encounter these challenges: the&#xA;proportions increased to 59% and 53% for respondents with less than two years&#xA;of experience with Go, respectively. These are both areas we hope to improve&#xA;via our &lt;code&gt;gonew&lt;/code&gt; prototype: templates can provide new Go developers with&#xA;well-tested project structures and design patterns, with initial&#xA;implementations written in idiomatic Go. These survey results have helped our&#xA;team to keep the purpose of &lt;code&gt;gonew&lt;/code&gt; focused on tasks the Go community most&#xA;struggle with.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/new_challenge.svg&#34; alt=&#34;Chart of challenges respondents&#xA;faced when starting new Go projects&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;A majority of respondents told us they either use templates or copy+paste code&#xA;from existing projects when starting a new Go project (58%). Among respondents&#xA;with less than five years of Go experience, this proportion increased to&#xA;nearly ⅔ (63%). This was an important confirmation that the template-based&#xA;approach in &lt;code&gt;gonew&lt;/code&gt; seems to meet developers where they already are, aligning&#xA;a common, informal approach with &lt;code&gt;go&lt;/code&gt; command-style tooling. This is further&#xA;supported by the common feature requests for project templates: a majority of&#xA;respondents requested 1) a pre-configured directory structure to organize&#xA;their project and 2) sample code for common tasks in the project domain. These&#xA;results are well-aligned with the challenges developers said they faced in the&#xA;previous section. The responses to this question also help tease apart the&#xA;difference between project structure and design patterns, with nearly twice as&#xA;many respondents saying they want Go project templates to provide the former&#xA;than the latter.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/new_approach.svg&#34; alt=&#34;Chart of approaches respondents&#xA;used when starting new Go projects&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/templates.svg&#34; alt=&#34;Chart of functionality respondents&#xA;requested when starting new Go projects&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;A majority of respondents told us the ability to make changes to a template&#xA;&lt;em&gt;and&lt;/em&gt; have those changes propagate to projects based on that template was of&#xA;at least moderate importance. Anecdotally, we haven&amp;rsquo;t spoken with any&#xA;developers who &lt;em&gt;currently&lt;/em&gt; have this functionality with home-grown template&#xA;approaches, but it suggests this is an interesting avenue for future&#xA;development.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/template_updates.svg&#34; alt=&#34;Chart of respondent interest&#xA;in updatable templates&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;err_handling&#34;&gt;Developer goals for error handling&lt;/h2&gt;&#xA;&lt;p&gt;A perennial topic of discussion among Go developers is potential improvements&#xA;to error handling. As one respondent summarized:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Error handling adds too much boilerplate (I know, you probably heard this&#xA;before)&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Open source Go developer w/ 1 &amp;ndash; 2&#xA;years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;But, we also hear from numerous developers that they appreciate Go&amp;rsquo;s approach&#xA;to error handling:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Go error handling is simple and effective. As I have backends in Java and&#xA;C# and exploring Rust and Zig now, I am always pleased to go back to write&#xA;Go code. And one of the reasons is, believe it or not, error handling. It is&#xA;really simple, plain and effective. Please leave it that way.&amp;rdquo; &lt;span&#xA;class=&#34;quote_source&#34;&gt;&amp;mdash; Open source Go developer w/ 5 &amp;ndash; 9 years of&#xA;experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Rather than ask about specific modifications to error handling in Go, we&#xA;wanted to better understand developers&amp;rsquo; higher-level goals and whether Go&amp;rsquo;s&#xA;current approach has proven useful and usable. We found that a majority of&#xA;respondents appreciate Go&amp;rsquo;s approach to error handling (55%) and say it helps&#xA;them know when to check for errors (50%). Both of these outcomes were stronger&#xA;for respondents with more Go experience, suggesting that either developers&#xA;grow to appreciate Go&amp;rsquo;s approach to error handling over time, or that this is&#xA;one factor leading developers to eventually leave the Go ecosystem (or at&#xA;least stop responding to Go-related surveys). Many survey respondents also&#xA;felt that Go requires a lot of tedious, boilerplate code to check for errors&#xA;(43%); this remained true regardless of how much prior Go experience&#xA;respondents had. Interestingly, when respondents said they appreciate Go&amp;rsquo;s&#xA;error handling, they were unlikely to say it also results in lots of&#xA;boilerplate code&amp;mdash;our team had a hypothesis that Go developers can both&#xA;appreciate the language&amp;rsquo;s approach to error handling and feel it&amp;rsquo;s too&#xA;verbose, but only 14% of respondents agreed with both statements.&lt;/p&gt;&#xA;&lt;p&gt;Specific issues that respondents cited include challenges knowing which error&#xA;types to check for (28%), wanting to easily show a stack trace along with the&#xA;error message (28%), and the ease with which errors can be entirely ignored&#xA;(19%). About ⅓ of respondents were also interested in adopting concepts from&#xA;other languages, such as Rust&amp;rsquo;s &lt;code&gt;?&lt;/code&gt; operator (31%).&lt;/p&gt;&#xA;&lt;p&gt;The Go team has no plans to add exceptions to the language, but since this is&#xA;anecdotally a common request, we included it as a response choice. Only 1 in&#xA;10 respondents said they wished they could use exceptions in Go, and this was&#xA;inversely related to experience&amp;mdash;more veteran Go developers were less likely&#xA;to be interested in exceptions than respondents newer to the Go community.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/error_handling.svg&#34; alt=&#34;Chart of respondents&#39; thoughts&#xA;about Go&#39;s error handling approach&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;mlai&#34;&gt;Understanding ML/AI use cases&lt;/h2&gt;&#xA;&lt;p&gt;The Go team is considering how the unfolding landscape of new ML/AI&#xA;technologies may impact software development in two distinct veins: 1) how&#xA;might ML/AI tooling help engineers write better software, and 2) how might Go&#xA;help engineers bring ML/AI support to their applications and services? Below,&#xA;we delve into each of these areas.&lt;/p&gt;&#xA;&lt;h3 id=&#34;helping-engineers-write-better-software&#34;&gt;Helping engineers write better software&lt;/h3&gt;&#xA;&lt;p&gt;There&amp;rsquo;s little denying we&amp;rsquo;re in &lt;a href=&#34;https://www.gartner.com/en/articles/what-s-new-in-artificial-intelligence-from-the-2023-gartner-hype-cycle&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;a hype cycle around the possibilities for&#xA;AI/ML&lt;/a&gt;.&#xA;We wanted to take a step back to focus on the broader challenges developers&#xA;face and where they think AI might prove useful in their regular work. The&#xA;answers were a bit surprising, especially given the industry&amp;rsquo;s current focus&#xA;on coding assistants.&lt;/p&gt;&#xA;&lt;p&gt;First, we see a few AI use cases that about half of respondents thought could&#xA;be helpful: generating tests (49%), suggesting best practices in-situ (47%),&#xA;and catching likely mistakes early in the development process (46%). A&#xA;unifying theme of these top use cases is that each could help improve the&#xA;quality and reliability of code an engineer is writing. A fourth use case&#xA;(help writing documentation) garnered interest from about ⅓ of respondents.&#xA;The remaining cases comprise a long tail of potentially fruitful ideas, but&#xA;these are of significantly less general interest than the top four.&lt;/p&gt;&#xA;&lt;p&gt;When we look at developers&amp;rsquo; duration of experience with Go, we find that&#xA;novice respondents are interested in help resolving compiler errors and&#xA;explaining what a piece of Go code does more than veteran Go developers. These&#xA;might be areas where AI could help improve the getting started experience for&#xA;new Gophers; for example, an AI assistant could help explain in natural&#xA;language what an undocumented block of code does, or suggest common solutions&#xA;to specific error messages. Conversely, we see no differences between&#xA;experience levels for topics like &amp;ldquo;catch common mistakes&amp;rdquo;&amp;mdash;both novice and&#xA;veteran Go developers say they would appreciate tooling to help with this.&lt;/p&gt;&#xA;&lt;p&gt;One can squint at this data and see three broad trends:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Respondents voiced interest in getting feedback from &amp;ldquo;expert reviewers&amp;rdquo; in&#xA;real-time, not just during review time.&lt;/li&gt;&#xA;&lt;li&gt;Generally, respondents appeared most interested in tooling that saves them&#xA;from potentially less-enjoyable tasks (e.g., writing tests or documenting&#xA;code).&lt;/li&gt;&#xA;&lt;li&gt;Wholesale writing or translating of code was of fairly low interest,&#xA;especially to developers with more than a year or two of experience.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Taken together, it appears that today, developers are less excited by the&#xA;prospect of machines doing the fun (e.g., creative, enjoyable, appropriately&#xA;challenging) parts of software development, but do see value in another set of&#xA;&amp;ldquo;eyes&amp;rdquo; reviewing their code and potentially handling dull or repetitive tasks&#xA;for them. As one respondent phrased it:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;I&amp;rsquo;m specifically interested in using AI/ML to improve my productivity with&#xA;Go. Having a system that is trained in Go best practices, can catch&#xA;anti-patterns, bugs, generate tests, with a low rate of hallucination, would&#xA;be killer.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer w/ 5 &amp;ndash;&#xA;9 years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This survey, however, is just one data point in a quickly-evolving research&#xA;field, so it&amp;rsquo;s best to keep these results in context.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/ml_use_cases.svg&#34; alt=&#34;Chart of respondents&#39; interest&#xA;in AI/ML support for development tasks&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;bringing-ai-features-to-applications-and-services&#34;&gt;Bringing AI features to applications and services&lt;/h3&gt;&#xA;&lt;p&gt;In addition to looking at how Go developers might benefit from AI/ML-powered&#xA;tooling, we explored their plans for building AI-powered applications and&#xA;services (or supporting infrastructure) with Go. We found that we&amp;rsquo;re still&#xA;early in &lt;a href=&#34;https://en.wikipedia.org/wiki/Technology_adoption_life_cycle&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;the adoption&#xA;curve&lt;/a&gt;: most&#xA;respondents have not yet tried to use Go in these areas, though every topic&#xA;saw some level of interest from roughly half of respondents. For example, a&#xA;majority of respondents reported interest in integrating the Go services they&#xA;work on with LLMs (49%), but only 13% have already done so or are currently&#xA;evaluating this use case. At the time of this survey, responses gently suggest&#xA;that developers may be most interested in using Go to call LLMs directly,&#xA;build the data pipelines needed to power ML/AI systems, and for creating API&#xA;endpoints other services can call to interact with ML/AI models. As one&#xA;example, this respondent described the benefits they hoped to gain by using Go&#xA;in their data pipelines:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;I want to integrate the ETL [extract, transform, and load] part using Go,&#xA;to keep a consistent, robust, reliable codebase.&amp;rdquo; &lt;span&#xA;class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer w/ 3 &amp;ndash; 4 years of&#xA;experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/ml_adoption.svg&#34; alt=&#34;Chart of respondents&#39; current use&#xA;of (and interest in) Go for AI/ML systems&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;err_msgs&#34;&gt;Toolchain error messages&lt;/h2&gt;&#xA;&lt;p&gt;Many developers can relate to the frustrating experience of seeing an error&#xA;message, thinking they know what it means and how to resolve it, but after&#xA;hours of fruitless debugging realize it meant something else entirely. One&#xA;respondent explained their frustration as follows:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;So often the printed complaints wind up having nothing to do with the&#xA;problem, but it can take an hour before I discover that that&amp;rsquo;s the case. The&#xA;error messages are unnervingly terse, and don&amp;rsquo;t seem to go out of their way&#xA;to guess as to what the user might be trying to do or [explain what they&amp;rsquo;re]&#xA;doing wrong.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer w/ 10+&#xA;years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;We believe the warnings and errors emitted by developer tooling should be&#xA;brief, understandable, and actionable: the human reading them should be able&#xA;to accurately understand what went wrong and what they can do to resolve the&#xA;issue. This is an admittedly high bar to strive for, and with this survey we&#xA;took some measurements to understand how developers perceive Go&amp;rsquo;s current&#xA;warning and error messages.&lt;/p&gt;&#xA;&lt;p&gt;When thinking about the most recent Go error message they worked through,&#xA;respondents told us there was much room for improvement. Only a small majority&#xA;understood what the problem was from the error message alone (54%), and even&#xA;fewer knew what to do next to resolve the issue (41%). It appears a relatively&#xA;small amount of additional information could meaningfully increase these&#xA;proportions, as ¼ of respondents said they mostly knew how to fix the problem,&#xA;but needed to see an example first. Further, with 11% of respondents saying&#xA;they couldn&amp;rsquo;t make sense of the error message, we now have a baseline for&#xA;current understandability of the Go toolchain&amp;rsquo;s error messages.&lt;/p&gt;&#xA;&lt;p&gt;Improvements to Go&amp;rsquo;s toolchain error messages would especially benefit&#xA;less-experienced Gophers. Respondents with up to two years of experience were&#xA;less likely than veteran Gophers to say they understood the problem (47% vs.&#xA;61%) or knew how to fix it (29% vs. 52%), and were twice as likely to need to&#xA;search online to fix the issue (21% vs. 9%) or even make sense of what the&#xA;error meant (15% vs. 7%).&lt;/p&gt;&#xA;&lt;p&gt;We hope to focus on improving toolchain error messages during 2024. These&#xA;survey results suggest this is an area of frustration for developers of all&#xA;experience levels, and will particularly help newer developers get started&#xA;with Go.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/err_exp.svg&#34; alt=&#34;Chart of error handling experiences&#34;&#xA;class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/err_exp_exp.svg&#34; alt=&#34;Chart of error handling&#xA;experiences, split by duration of Go experience&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;To understand &lt;em&gt;how&lt;/em&gt; these messages might be improved, we asked survey&#xA;respondents an open-ended question: &amp;ldquo;If you could make a wish and improve one&#xA;thing about error messages in the Go toolchain, what would you change?&amp;rdquo;. The&#xA;responses largely align with our hypothesis that good error messages are both&#xA;understandable and actionable. The most common response was some form of &amp;ldquo;Help&#xA;me understand what led to this error&amp;rdquo; (36%), 21% of respondents explicitly&#xA;asked for guidance to fix the problem, and 14% of respondents called out&#xA;languages such as Rust or Elm as exemplars which strive to do both of these&#xA;things. In the words of one respondent:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;For compilation errors, Elm or Rust-style output pinpointing exact issue in&#xA;the source code. Errors should include suggestions to fix them where&#xA;possible&amp;hellip; I think a general policy of &amp;lsquo;optimize error output to be read by&#xA;humans&amp;rsquo; with &amp;lsquo;provide suggestions where possible&amp;rsquo; would be very welcome&#xA;here.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer w/ 5 &amp;ndash; 9&#xA;years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Understandably, there is a fuzzy conceptual boundary between toolchain error&#xA;messages and runtime error messages. For example, one of the top requests&#xA;involved improved stack traces or other approaches to assist debugging runtime&#xA;crashes (22%). Similarly, a surprising theme in 4% of the feedback was about&#xA;challenges with getting help from the &lt;code&gt;go&lt;/code&gt; command itself. These are great&#xA;examples of the Go community helping us identify related pain points that&#xA;weren&amp;rsquo;t otherwise on our radar. We started this investigation focused on&#xA;improving compile-time errors, but one of the core areas Go developers would&#xA;like to see improved actually relates to run-time errors, while another was&#xA;about the &lt;code&gt;go&lt;/code&gt; command&amp;rsquo;s help system.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;When an error is thrown, the call stack can be huge and includes a bunch of&#xA;files I don&amp;rsquo;t care about. I just want to know where the problem is in MY&#xA;code, not the library I&amp;rsquo;m using, or how the panic was handled.&amp;rdquo; &lt;span&#xA;class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer w/ 1 &amp;ndash; 2 years of&#xA;experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Getting help via `go help run` dumps a wall of text, with links to&#xA;further readings to find the available command-line flags. Or the fact that&#xA;it understands `go run &amp;ndash;help` but instead of showing the help, it says&#xA;&amp;lsquo;please run go help run instead&amp;rsquo;. Just show me list of flags in `go run&#xA;&amp;ndash;help`.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer w/ 3 &amp;ndash;&#xA;4 years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/text_err_wish.svg&#34; alt=&#34;Chart of potential improvements&#xA;for Go&#39;s error messages&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;microservices&#34;&gt;Microservices&lt;/h2&gt;&#xA;&lt;p&gt;We commonly hear that developers find Go to be a great fit for microservices,&#xA;but we have never tried to quantify how many Go developers have adopted this&#xA;type of service architecture, understand how those services communicate with&#xA;one another, or the challenges developers encounter when working on them. This&#xA;year we added a few questions to better understand this space.&lt;/p&gt;&#xA;&lt;p&gt;A plurality of respondents said they work mostly on microservices (43%), with&#xA;another ¼ saying they work on a mix of both microservices and monoliths. Only&#xA;about ⅕ of respondents work mostly on monolithic Go applications. This is one&#xA;of the few areas where we see differences based on the size of organization&#xA;respondents work at&amp;mdash;large organizations seem more likely to have adopted a&#xA;microservice architecture than smaller companies. Respondents from large&#xA;organizations (&amp;gt;1,000 employees) were most likely to say they work on&#xA;microservices (55%), with only 11% of these respondents working primarily on&#xA;monoliths.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/service_arch.svg&#34; alt=&#34;Chart of respondents&#39; primary&#xA;service architecture&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;We see some bifurcation in the number of microservices comprising Go&#xA;platforms. One group is composed of a handful (2 to 5) of services (40%),&#xA;while the other consists of larger collections, with a minimum of 10 component&#xA;services (37%). The number of microservices involved does not appear to be&#xA;correlated with organization size.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/service_num.svg&#34; alt=&#34;Chart of the number of&#xA;microservices respondents&#39; systems involve&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;A large majority of respondents use some form of direct response request&#xA;(e.g., RPC, HTTP, etc.) for microservice communication (72%). A smaller&#xA;proportion use message queues (14%) or a pub/sub approach (9%); again, we see&#xA;no differences here based on organization size.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/service_comm.svg&#34; alt=&#34;Chart of how microservices&#xA;communicate with one another&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;A majority of respondents build microservices in a polyglot of languages, with&#xA;only about ¼ exclusively using Go. Python is the most common companion&#xA;language (33%), alongside Node.js (28%) and Java (26%). We again see&#xA;differences based on organization size, with larger organizations more likely&#xA;to be integrating Python (43%) and Java (36%) microservices, while smaller&#xA;organizations are a bit more likely to only use Go (30%). Other languages&#xA;appeared to be used equally based on organization size.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/service_lang.svg&#34; alt=&#34;Chart of other languages that Go&#xA;microservices interact with&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Overall, respondents told us testing and debugging were their biggest&#xA;challenge when writing microservice-based applications, followed by&#xA;operational complexity. Many other challenges occupy the long tail on this&#xA;graph, though &amp;ldquo;portability&amp;rdquo; stands out as a non-issue for most respondents. We&#xA;interpret this to mean that such services aren&amp;rsquo;t intended to be portable&#xA;(beyond basic containerization); for example, if an organization&amp;rsquo;s&#xA;microservices are initially powered by PostgreSQL databases, developers aren&amp;rsquo;t&#xA;concerned with potentially porting this to an Oracle database in the near&#xA;future.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/service_challenge.svg&#34; alt=&#34;Chart of challenges&#xA;respondents face when writing microservice-based applications&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;modules&#34;&gt;Module authorship and maintenance&lt;/h2&gt;&#xA;&lt;p&gt;Go has a vibrant ecosystem of community-driven modules, and we want to&#xA;understand the motivations and challenges faced by developers who maintain&#xA;these modules. We found that about ⅕ of respondents maintain (or used to&#xA;maintain) an open-source Go module. This was a surprisingly high proportion,&#xA;and may be biased due to how we share this survey: module maintainers may be&#xA;more likely to closely follow the Go blog (where this survey is announced)&#xA;than other Go developers.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/mod_maintainer.svg&#34; alt=&#34;Chart of how many respondents&#xA;have served as a maintainer for a public Go module&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Module maintainers appear to be largely self-motivated&amp;mdash;they report working&#xA;on modules that they need for personal (58%) or work (56%) projects, that they&#xA;do so because they enjoy working on these modules (63%) and being part of the&#xA;public Go community (44%), and that they learn useful skills from their module&#xA;maintainership (44%). More external motivations, such as receiving recognition&#xA;(15%), career advancement (36%), or cash money (20%) are towards the bottom of&#xA;the list.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/mod_motivation.svg&#34; alt=&#34;Chart of the motivations of&#xA;public module maintainers&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Given the forms of &lt;a href=&#34;https://en.wikipedia.org/wiki/Motivation#Intrinsic_and_extrinsic&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;intrinsic&#xA;motivation&lt;/a&gt; identified above, it&#xA;follows that a key challenge for module maintainers is finding time to devote&#xA;to their module (41%). While this might not seem like an actionable finding in&#xA;itself (we can&amp;rsquo;t give Go developers an extra hour or two each day, right?),&#xA;it&amp;rsquo;s a helpful lens through which to view module tooling and&#xA;development&amp;mdash;these tasks are most likely occurring while the developer is&#xA;already pressed for time, and perhaps it&amp;rsquo;s been weeks or months since they&#xA;last had an opportunity to work on it, so things aren&amp;rsquo;t fresh in their memory.&#xA;Thus, aspects like understandable and actionable error messages can be&#xA;particularly helpful: rather than require someone to once again search for&#xA;specific &lt;code&gt;go&lt;/code&gt; command syntax, perhaps the error output could provide the&#xA;solution they need right in their terminal.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/mod_challenge.svg&#34; alt=&#34;Chart of challenges respondents&#xA;face when maintaining public Go modules&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;demographics&#34;&gt;Demographics&lt;/h2&gt;&#xA;&lt;p&gt;Most survey respondents reported using Go for their primary job (78%), and a&#xA;majority (59%) said they use it for personal or open-source projects. In fact,&#xA;it&amp;rsquo;s common for respondents to use Go for &lt;em&gt;both&lt;/em&gt; work and personal/OSS&#xA;projects, with 43% of respondents saying they use Go in each of these&#xA;situations.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/where.svg&#34; alt=&#34;Chart of situations in which&#xA;respondents recently used Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;The majority of respondents have been working with Go for under five years&#xA;(68%). As we&amp;rsquo;ve seen in &lt;a href=&#34;/blog/survey2023-q1-results#novice-respondents-are-more-likely-to-prefer-windows-than-more-experienced-respondents&#34;&gt;prior&#xA;years&lt;/a&gt;,&#xA;people who found this survey via VS Code tended to be less experienced than&#xA;people who found the survey via other channels.&lt;/p&gt;&#xA;&lt;p&gt;When we break down where people use Go by their experience level, two findings&#xA;stand out. First, a majority of respondents from all experience levels said&#xA;they&amp;rsquo;re using Go professionally; indeed, for people with over two years of&#xA;experience, the vast majority use Go at work (85% &amp;ndash; 91%). A similar trend&#xA;exists for open-source development. The second finding is that developers with&#xA;less Go experience are more likely to be using Go to expand their skill set&#xA;(38%) or to evaluate it for use at work (13%) than more experienced Go&#xA;developers. We interpret this to mean that many Gophers initially view Go as&#xA;part of &amp;ldquo;upskilling&amp;rdquo; or expanding their understanding of software development,&#xA;but that within a year or two, they look to Go as more of a tool for doing&#xA;than learning.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/go_exp.svg&#34; alt=&#34;Chart of how long respondents have&#xA;been working with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/where_exp.svg&#34; alt=&#34;Chart of situations in which&#xA;respondents recently used Go, split by their level of Go experience&#34;&#xA;class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;The most common use cases for Go continue to be API/RPC services (74%) and&#xA;command line tools (62%). People tell us Go is a great choice for these types&#xA;of software for several reasons, including its built-in HTTP server and&#xA;concurrency primitives, ease of cross-compilation, and single-binary&#xA;deployments.&lt;/p&gt;&#xA;&lt;p&gt;The intended audience for much of this tooling is in business settings (62%),&#xA;with 17% of respondents reporting that they develop primarily for more&#xA;consumer-oriented applications. This isn&amp;rsquo;t surprising given the low use of Go&#xA;for consumer-focused applications such as desktop, mobile, or gaming, vs. its&#xA;very high use for backend services, CLI tooling, and cloud development, but it&#xA;is a useful confirmation of how heavily Go is used in B2B settings.&lt;/p&gt;&#xA;&lt;p&gt;We also looked for differences based on respondents&amp;rsquo; level of experience with&#xA;Go and organization size. More experienced Go developers reported building a&#xA;wider variety of different things in Go; this trend was consistent across&#xA;every category of app or service. We did not find any notable differences in&#xA;what respondents are building based on their organization size.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/what.svg&#34; alt=&#34;Chart of the types of things respondents&#xA;are building with Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/enduser.svg&#34; alt=&#34;Chart of the audience using the&#xA;software respondents build&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Respondents were about equally likely to say this was the first time they&amp;rsquo;ve&#xA;responded to the Go Developer Survey vs. saying they had taken this survey&#xA;before. There is a meaningful difference between people who learned about this&#xA;survey via the Go blog, where 61% reported taking this survey previously, vs.&#xA;people who learned about this survey via a notification in VS Code, where only&#xA;31% said they&amp;rsquo;ve previously taken this survey. We don&amp;rsquo;t expect people to&#xA;perfectly recall every survey they&amp;rsquo;ve responded to on the internet, but this&#xA;gives us some confidence that we&amp;rsquo;re hearing from a balanced mix of new and&#xA;repeat respondents with each survey. Further, this tells us our combination of&#xA;social media posts and random in-editor sampling are both necessary for&#xA;hearing from a diverse set of Go developers.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/return_respondent.svg&#34; alt=&#34;Chart of how many&#xA;respondents said they have taken this survey before&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;firmographics&#34;&gt;Firmographics&lt;/h2&gt;&#xA;&lt;p&gt;Respondents to this survey reported working at a mix of different&#xA;organizations, from thousand-person-plus enterprises (27%), to midsize&#xA;businesses (25%) and smaller organizations with &amp;lt; 100 employees (44%). About&#xA;half of respondents work in the technology industry (50%), a large increase&#xA;over the next most-common industry&amp;mdash;financial services&amp;mdash;at 13%.&lt;/p&gt;&#xA;&lt;p&gt;This is statistically unchanged from the past few Go Developer Surveys&amp;mdash;we&#xA;continue to hear from people in different countries and in organizations of&#xA;different sizes and industries at consistent rates year after year.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/org_size.svg&#34; alt=&#34;Chart of the different organization&#xA;sizes where respondents use Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/industry.svg&#34; alt=&#34;Chart of the different industries&#xA;where respondents use Go&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/location.svg&#34; alt=&#34;Chart of countries or regions where&#xA;respondents are located&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;methodology&#34;&gt;Methodology&lt;/h2&gt;&#xA;&lt;p&gt;Most survey respondents &amp;ldquo;self-selected&amp;rdquo; to take this survey, meaning they&#xA;found it on the Go blog or other social Go channels. A potential problem with&#xA;this approach is that people who don&amp;rsquo;t follow these channels are less likely&#xA;to learn about the survey, and might respond differently than people who do&#xA;closely follow them. About 40% of respondents were randomly sampled, meaning&#xA;they responded to the survey after seeing a prompt for it in VS Code (everyone&#xA;using the VS Code Go plugin between mid-July &amp;ndash; mid-August 2023 had a 10% of&#xA;receiving this random prompt). This randomly sampled group helps us generalize&#xA;these findings to the larger community of Go developers.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-read-these-results&#34;&gt;How to read these results&lt;/h3&gt;&#xA;&lt;p&gt;Throughout this report we use charts of survey responses to provide supporting&#xA;evidence for our findings. All of these charts use a similar format. The title&#xA;is the exact question that survey respondents saw. Unless otherwise noted,&#xA;questions were multiple choice and participants could only select a single&#xA;response choice; each chart&amp;rsquo;s subtitle will tell the reader if the question&#xA;allowed multiple response choices or was an open-ended text box instead of a&#xA;multiple choice question. For charts of open-ended text responses, a Go team&#xA;member read and manually categorized the responses. Many open-ended questions&#xA;elicited a wide variety of responses; to keep the chart sizes reasonable, we&#xA;condensed them to a maximum of the top 10 themes, with additional themes all&#xA;grouped under &amp;ldquo;Other&amp;rdquo;. The percentage labels shown in charts are rounded to&#xA;the nearest integer (e.g., 1.4% and 0.8% will both be displayed as 1%), but&#xA;the length of each bar and row ordering are based on the unrounded values.&lt;/p&gt;&#xA;&lt;p&gt;To help readers understand the weight of evidence underlying each finding, we&#xA;included error bars showing the 95% &lt;a href=&#34;https://en.wikipedia.org/wiki/Confidence_interval&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;confidence&#xA;interval&lt;/a&gt; for responses;&#xA;narrower bars indicate increased confidence. Sometimes two or more responses&#xA;have overlapping error bars, which means the relative order of those responses&#xA;is not statistically meaningful (i.e., the responses are effectively tied).&#xA;The lower right of each chart shows the number of people whose responses are&#xA;included in the chart, in the form &amp;ldquo;n = [number of respondents]&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;We include select quotes from respondents to help clarify many of our&#xA;findings. These quotes include the length of times the respondent has used Go.&#xA;If the respondent said they use Go at work, we refer to them as a&#xA;&amp;ldquo;professional Go developer&amp;rdquo;; if they don&amp;rsquo;t use Go at work but do use Go for&#xA;open-source development, we refer to them as an &amp;ldquo;open-source Go developer&amp;rdquo;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;closing&#34;&gt;Closing&lt;/h2&gt;&#xA;&lt;p&gt;The final question on our survey always asks respondents whether there&amp;rsquo;s&#xA;anything else they&amp;rsquo;d like to share with us about Go. The most common piece of&#xA;feedback people provide is &amp;ldquo;thanks!&amp;rdquo;, and this year was no different (33%). In&#xA;terms of requested language improvements, we see a three-way statistical tie&#xA;between improved expressivity (12%), improved error handling (12%), and&#xA;improved type safety or reliability (9%). Respondents had a variety of ideas&#xA;for improving expressivity, with the general trend of this feedback being&#xA;&amp;ldquo;Here&amp;rsquo;s a specific thing I write frequently, and I wish it were easier to&#xA;express this in Go&amp;rdquo;. The issues with error handling continue to be complaints&#xA;about the verbosity of this code today, while feedback about type safety most&#xA;commonly touched on &lt;a href=&#34;https://en.wikipedia.org/wiki/Tagged_union&#34; rel=&#34;noreferrer&#34; target=&#34;_blank&#34;&gt;sum types&lt;/a&gt;.&#xA;This type of high-level feedback is extremely useful when the Go team tries to&#xA;plan focus areas for the coming year, as it tells us general directions in&#xA;which the community is hoping to steer the ecosystem.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;I know about Go&amp;rsquo;s attitude towards simplicity and I appreciate it. I just&#xA;wish there [were] slightly more features. For me it would be better error&#xA;handling (not exceptions though), and maybe some common creature comforts&#xA;like map/reduce/filter and ternary operators. Anything not too obscure&#xA;that&amp;rsquo;ll save me some &amp;lsquo;if&amp;rsquo; statements.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash;&#xA;Professional Go developer w/ 1 &amp;ndash; 2 years of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Please keep Go in line with the long term values Go established so long ago&#xA;— language and library stability. [&amp;hellip;] It is an environment I can&#xA;rely on to not break my code after 2 or 3 years. For that, thank you very&#xA;much.&amp;rdquo; &lt;span class=&#34;quote_source&#34;&gt;&amp;mdash; Professional Go developer w/ 10+ years&#xA;of experience&lt;/span&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;survey2023h2/text_anything_else.svg&#34; alt=&#34;Chart of other topics&#xA;respondents shared with us&#34; class=&#34;chart&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s all for this bi-annual iteration of the Go Developer Survey. Thanks to&#xA;everyone who shared their feedback about Go&amp;mdash;we have immense gratitude for&#xA;taking your time to help shape Go&amp;rsquo;s future, and we hope you see some of your&#xA;own feedback reflected in this report. 🩵&lt;/p&gt;&#xA;&lt;p&gt;&amp;mdash; Todd (on behalf of the Go team at Google)&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;Article prevnext&#34;&gt;&#xA;    &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;        &lt;p&gt;&#xA;        &#xA;          &#xA;            &lt;b&gt;Next article: &lt;/b&gt;&lt;a href=&#34;/blog/deadcode&#34;&gt;Finding unreachable functions with deadcode&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &#xA;          &#xA;            &lt;b&gt;Previous article: &lt;/b&gt;&lt;a href=&#34;/blog/14years&#34;&gt;Fourteen Years of Go&lt;/a&gt;&lt;br&gt;&#xA;          &#xA;        &#xA;        &lt;b&gt;&lt;a href=&#34;/blog/all&#34;&gt;Blog Index&lt;/a&gt;&lt;/b&gt;&#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;      &#xA;    &#xA;    &lt;/div&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script src=&#34;/js/jquery.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/playground.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/play.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/js/godocs.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;</content></entry></feed>

If you would like to create a banner that links to this page (i.e. this validation result), do the following:

  1. Download the "valid Atom 1.0" banner.

  2. Upload the image to your own server. (This step is important. Please do not link directly to the image on this server.)

  3. Add this HTML to your page (change the image src attribute if necessary):

If you would like to create a text link instead, here is the URL you can use:

http://www.feedvalidator.org/check.cgi?url=http%3A//blog.golang.org/feed.atom

Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda