| go fmt your code |
| 23 Jan 2013 |
| Tags: gofix, gofmt, technical |
| |
| Andrew Gerrand |
| |
| * Introduction |
| |
| [[https://golang.org/cmd/gofmt/][Gofmt]] is a tool that automatically formats Go source code. |
| |
| Gofmt'd code is: |
| |
| - easier to *write*: never worry about minor formatting concerns while hacking away, |
| |
| - easier to *read*: when all code looks the same you need not mentally convert |
| others' formatting style into something you can understand. |
| |
| - easier to *maintain*: mechanical changes to the source don't cause unrelated |
| changes to the file's formatting; |
| diffs show only the real changes. |
| |
| - *uncontroversial*: never have a debate about spacing or brace position ever again! |
| |
| * Format your code |
| |
| We recently conducted a survey of Go packages in the wild and found that |
| about 70% of them are formatted according to gofmt's rules. |
| This was more than expected - and thanks to everyone who uses gofmt - but |
| it would be great to close the gap. |
| |
| To format your code, you can use the gofmt tool directly: |
| |
| gofmt -w yourcode.go |
| |
| Or you can use the "[[https://golang.org/cmd/go/#hdr-Run_gofmt_on_package_sources][go fmt]]" command: |
| |
| go fmt path/to/your/package |
| |
| To help keep your code in the canonical style, |
| the Go repository contains hooks for editors and version control systems |
| that make it easy to run gofmt on your code. |
| |
| For Vim users, the [[https://github.com/fatih/vim-go][Vim plugin for Go]] |
| includes the :Fmt command that runs gofmt on the current buffer. |
| |
| For emacs users, [[https://github.com/dominikh/go-mode.el][go-mode.el]] |
| provides a gofmt-before-save hook that can be installed by adding this line |
| to your .emacs file: |
| |
| (add-hook 'before-save-hook #'gofmt-before-save) |
| |
| For Eclipse or Sublime Text users, the [[https://github.com/GoClipse/goclipse][GoClipse]] |
| and [[https://github.com/DisposaBoy/GoSublime][GoSublime]] projects add |
| a gofmt facility to those editors. |
| |
| And for Git aficionados, the [[https://github.com/golang/go/blob/release-branch.go1.1/misc/git/pre-commit][misc/git/pre-commit script]] |
| is a pre-commit hook that prevents incorrectly-formatted Go code from being committed. |
| If you use Mercurial, the [[https://bitbucket.org/fhs/hgstyle/overview][hgstyle plugin]] |
| provides a gofmt pre-commit hook. |
| |
| * Mechanical source transformation |
| |
| One of the greatest virtues of machine-formatted code is that it can be |
| transformed mechanically without generating unrelated formatting noise in the diffs. |
| Mechanical transformation is invaluable when working with large code bases, |
| as it is both more comprehensive and less error prone than making wide-sweeping changes by hand. |
| Indeed, when working at scale (like we do at Google) it often isn't practical |
| to make these kinds of changes manually. |
| |
| The easiest way to mechanically manipulate Go code is with gofmt's -r flag. |
| The flag specifies a rewrite rule of the form |
| |
| pattern -> replacement |
| |
| where both pattern and replacement are valid Go expressions. |
| In the pattern, single-character lowercase identifiers serve as wildcards |
| matching arbitrary sub-expressions, |
| and those expressions are substituted for the same identifiers in the replacement. |
| |
| For example, this[[https://golang.org/cl/7038051][ recent change]] to the |
| Go core rewrote some uses of [[https://golang.org/pkg/bytes/#Compare][bytes.Compare]] |
| to use the more efficient [[https://golang.org/pkg/bytes/#Equal][bytes.Equal]]. |
| The contributor made the change using just two gofmt invocations: |
| |
| gofmt -r 'bytes.Compare(a, b) == 0 -> bytes.Equal(a, b)' |
| gofmt -r 'bytes.Compare(a, b) != 0 -> !bytes.Equal(a, b)' |
| |
| Gofmt also enables [[https://golang.org/cmd/fix/][gofix]], |
| which can make arbitrarily complex source transformations. |
| Gofix was an invaluable tool during the early days when we regularly made |
| breaking changes to the language and libraries. |
| For example, before Go 1 the built-in error interface didn't exist and the |
| convention was to use the os.Error type. |
| When we [[https://golang.org/doc/go1.html#errors][introduced error]], |
| we provided a gofix module that rewrote all references to os.Error and its |
| associated helper functions to use error and the new [[https://golang.org/pkg/errors/][errors package]]. |
| It would have been daunting to attempt by hand, |
| but with the code in a standard format it was relatively easy to prepare, |
| execute, and review this change which touched almost all Go code in existence. |
| |
| For more about gofix, see [[https://blog.golang.org/introducing-gofix][this article]]. |