Life without line numbers for 6% smaller Go binaries
Since the Go compiler is so primitive you can strongly influence the size of the program by just restructuring it. An example: if you have a function that converts integer return codes to errors, and you have another function that calls it a lot:<p><pre><code>  func codeToError(i int) error {
    switch i {
       case ...
       ...
    }
  }

  func stuff() error {
    if rv := callJunk(); rv &lt; 0 {
      return codeToError(rv)
    }

    if rv := moreJunk(); rv &lt; 0 {
      return codeToError(rv)
    }

    ...

    return nil
  }
</code></pre>
You&#x27;re going to get multiple whole copies of the inner function inlined into the outer one. This can add up, if the outer function is long and&#x2F;or if the inner switch statement is huge.<p>You can save a lot of code by jumping through an adapter function instead, like:<p><pre><code>  func callWithErrorsConverted(f func() int, g func(int) error) error {
    return g(f())
  }
</code></pre>
... because now the compiler doesn&#x27;t get to inline g into f. These things make a big difference in whole-program size. I wrote about it in the context of tailscale and protobufs here:<p><a href="https:&#x2F;&#x2F;paper.dropbox.com&#x2F;doc&#x2F;Bloaty-Puffs-and-the-Go-Compiler--A4NFFR1SRcfOaz0kMw0ITuQ0AQ-YiblPOe6AD2tKfEj5RzFT" rel="nofollow">https:&#x2F;&#x2F;paper.dropbox.com&#x2F;doc&#x2F;Bloaty-Puffs-and-the-Go-Compil...</a>