spacemacs/layers/+lang/go/README.org
Jay Z 34a446724f
Add Go command variables
This is a squash commit, it includes:
* Add go run and go test command variables
* Update go README for go-run-command and go-test-command
* Update CHANGELOG
2020-06-11 00:12:56 +02:00

318 lines
14 KiB
Org Mode

#+TITLE: Go layer
#+TAGS: general|layer|multi-paradigm|programming
[[file:img/go.png]]
* Table of Contents :TOC_5_gh:noexport:
- [[#description][Description]]
- [[#features][Features:]]
- [[#install][Install]]
- [[#layer][Layer]]
- [[#choosing-a-backend][Choosing a backend]]
- [[#pre-requisites][Pre-requisites]]
- [[#configuration][Configuration]]
- [[#execution][Execution]]
- [[#indentation][Indentation]]
- [[#autoformat][Autoformat]]
- [[#linting][Linting]]
- [[#tests][Tests]]
- [[#coverage][Coverage]]
- [[#guru][Guru]]
- [[#auto-completion][Auto-completion]]
- [[#lsp-backend][LSP backend]]
- [[#debugger][Debugger]]
- [[#working-with-go][Working with Go]]
- [[#go-commands-start-with-m][Go commands (start with =m=):]]
- [[#go-guru][Go Guru]]
- [[#refactoring][Refactoring]]
* Description
This layer adds extensive support for the [[https://golang.org][Go]] programming language.
** Features:
- Run [[https://golang.org/cmd/gofmt/][gofmt]] / [[https://godoc.org/golang.org/x/tools/cmd/goimports][goimports]] on file save (see [[#autoformat][Autoformat]])
- Auto-completion using [[https://github.com/nsf/gocode/tree/master/emacs][go-autocomplete.el]], via the =auto-completion= layer (see [[#auto-completion][Auto-completion]])
- Source analysis using [[https://docs.google.com/document/d/1_Y9xCEMj5S-7rv2ooHpZNH15JgRT5iM742gJkw5LtmQ][go-guru]] (see [[#guru][Guru]])
- Refactoring with [[http://gorefactor.org/][godoctor]]
- Edit struct field tags with [[https://github.com/fatih/gomodifytags][gomodifytags]]
- Linting with flycheck's built-in checkers or [[https://github.com/golangci/golangci-lint][golangci-lint]] (see [[#linting][Linting]])
- Test generation via [[https://github.com/s-kostyaev/go-gen-test][go-gen-test]] (see [[#tests][Tests]])
- Coverage profile visualization (see [[#coverage][Coverage]])
- List packages faster with [[https://github.com/haya14busa/gopkgs][gopkgs]]
- Fill a structure with default values using the [[https://github.com/davidrjenni/reftools/tree/master/cmd/fillstruct][fillstruct]]
- LSP backend (see [[#lsp-backend][LSP backend]])
- Interactive debugger using [[https://github.com/emacs-lsp/dap-mode][dap-mode]]
* Install
** Layer
To use this configuration layer, add it to your =~/.spacemacs=. You will need to
add =go= to the existing =dotspacemacs-configuration-layers= list in this file.
** Choosing a backend
To choose a default backend set the layer variable =go-backend=:
#+BEGIN_SRC elisp
(go :variables go-backend 'go-mode)
#+END_SRC
Alternatively the =lsp= backend will be automatically chosen if the layer =lsp=
is used and you did not specify any value for =go-backend=.
Backend can be chosen on a per project basis using directory local variables
(files named =.dir-locals.el= at the root of a project), an example to use the
=lsp= backend:
#+BEGIN_SRC elisp
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
((go-mode (go-backend . lsp)))
#+END_SRC
*Note:* you can easily add a directory local variable with ~SPC f v d~.
** Pre-requisites
You will need =gocode=, =gogetdoc=, =godef=, =godoctor= and many others
to get all the goodies of this layer:
#+BEGIN_SRC sh
GO111MODULE=on go get -v golang.org/x/tools/gopls@latest
GO111MODULE=on CGO_ENABLED=0 go get -v -trimpath -ldflags '-s -w' github.com/golangci/golangci-lint/cmd/golangci-lint
go get -u -v golang.org/x/tools/cmd/godoc
go get -u -v golang.org/x/tools/cmd/goimports
go get -u -v golang.org/x/tools/cmd/gorename
go get -u -v golang.org/x/tools/cmd/guru
go get -u -v github.com/cweill/gotests/...
go get -u -v github.com/davidrjenni/reftools/cmd/fillstruct
go get -u -v github.com/fatih/gomodifytags
go get -u -v github.com/godoctor/godoctor
go get -u -v github.com/haya14busa/gopkgs/cmd/gopkgs
go get -u -v github.com/josharian/impl
go get -u -v github.com/mdempsky/gocode
go get -u -v github.com/rogpeppe/godef
go get -u -v github.com/zmb3/gogetdoc
#+END_SRC
Make sure that the executables are in your search =$PATH=. Note that they are
installed on =$(go env GOPATH)/bin=, or =$GOBIN= if that environment variable is
defined. For information about setting up =$PATH=, check out the corresponding
section in the FAQ (~SPC h f $PATH RET~).
For best results, make sure that the =auto-completion= and =syntax-checking=
layers are enabled as well.
* Configuration
** Execution
By default, the go run command is =go run=. If you want to use a different
command or run with environment variables, set the layer variable
=go-run-command=.
#+BEGIN_SRC emacs-lisp
(go :variables go-run-command "ENV_VAR=foo go run")
#+END_SRC
To run the current =main= package with command line arguments, set the value of
=go-run-args= as a file local variable, e.g.
#+BEGIN_SRC emacs-lisp
// Local Variables:
// go-run-args: "--output run.log"
// End:
#+END_SRC
** Indentation
By default, the tab width in Go mode is 8 spaces. To use a different value, set
the layer variable =go-tab-width=, e.g.
#+BEGIN_SRC emacs-lisp
(go :variables go-tab-width 4)
#+END_SRC
If you're using =.editorconfig= in your project, set the value to nil to avoid
conflicts, i.e.
#+BEGIN_SRC emacs-lisp
(go :variables go-tab-width nil)
#+END_SRC
** Autoformat
To run =gofmt= before save, set the value to a non-nil, i.e.
#+BEGIN_SRC emacs-lisp
(go :variables go-format-before-save t)
#+END_SRC
To use a different formatter, set the value of =gofmt-command=, e.g.
#+BEGIN_SRC emacs-lisp
(go :variables gofmt-command "goimports")
#+END_SRC
** Linting
If you wish to use =golangci-lint=, set the following layer variable to non-nil:
#+BEGIN_SRC emacs-lisp
(go :variables go-use-golangci-lint t)
#+END_SRC
Check [[https://github.com/golangci/golangci-lint][golangci-lint]] and [[https://github.com/weijiangan/flycheck-golangci-lint][flycheck-golangci-lint]] for more details.
Please remember that without properly configured =flycheck-golangci-lint= variables =golangci-lint=
may not run as expected. The recommended way is to use a =.golangi.yml= in your project.
But if this is not possible you can also set global command line flags for =golangci-lint=.
Especially important is the selection of which linters to run and whether to lint test files too.
It may happen from time to time that =golangci-lint= is not able to parse a buffers content
properly. This normally happens when there are basic errors in the file which prevent more
complex analytics to run. In this case a set of errors will be shown at the top of the
current buffer which are not properly parsed by flycheck. Spacemacs still shows basic
errors in your buffer. When these have been fixed =golangci-lint= will regenerate
and further diagnostic data will be made available.
When this happens please report a bug to `golangci-lint` they are working hard
to fix these.
** Tests
If you're using =gocheck= or =testify= in your project you can use the
=go-use-gocheck-for-testing= or =go-use-testify-for-testing= variable to enable
suite testing and to get single function testing to work.
Tests are run in a compilation buffer displayed in a popup window that can be
closed by pressing ~C-g~ from any other window. The variable =go-test-buffer-name=
can be customized to set the output buffer name.
By default, the go test command is =go test=. If you want to use a different
command or test with environment variables, set the layer variable
=go-test-command=.
#+BEGIN_SRC emacs-lisp
(go :variables go-test-command "ENV_VAR=foo go test")
#+END_SRC
To provide additional arguments to =go test=, specify =go-use-test-args=.
#+BEGIN_SRC emacs-lisp
(go :variables go-use-test-args "-race -timeout 10s")
#+END_SRC
** Coverage
=go-coverage-display-buffer-func= controls how =go-coverage= should display
the coverage buffer. See [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Choosing-Window.html][display-buffer]] for a list of possible functions.
The default value is =display-buffer-reuse-window=.
** Guru
If you would like to use the =Go Guru= bindings in your work, in your project you
will need to set the scope with ~SPC m f o~. The scope is a comma separated set
of packages, and Go's recursive operator is supported. In addition, you can
prefix it with =-= to exclude a package from searching.
** Auto-completion
For auto-completion there are actually two choices. First there is the classic
=gocode=. This has been around for quite a long time now, however =gocode= has many
shortcomings, like not being able to show documentation for built-in objects or
being fully dependent on installed binary files to provide its suggestions.
A more modern and complete solution is provided by =gogetdoc=, which is able to
precisely detect all documentations in your go projects independently from where
they have been added. This is also the recommended choice from =go-mode.el=.
To choose =gocode= nothing more needs to be done. To use =gogetdoc= you need to set
the layer variable:
#+BEGIN_SRC emacs-lisp
(go :variables godoc-at-point-function 'godoc-gogetdoc)
#+END_SRC
If you choose to use =gocode= there are some suggestions to improve its results.
As =gocode= uses the output from installed binary files to provide its suggestions.
You have a few options to ensure you always get up to date suggestions:
- Run =go install ./...= in your package directory when you make a file change.
- Run =gocode set autobuild true= to have gocode attempt to run =go install ./...=
for you.
- You can configure your task runner to run the =go install ./...= command on every
file change.
** LSP backend
To enable the LSP backend, ensure that the =lsp= layer is enabled, and set the
layer variable =go-backend=:
#+BEGIN_SRC elisp
(go :variables go-backend 'lsp)
#+END_SRC
You can check [[https://www.github.com/emacs-lsp/lsp-mode/][lsp-mode]] for the gory details.
The backend can be chosen on a per project basis using directory local variables
(files named =.dir-locals.el= at the root of a project), an example is to use the
=go-mode= backend:
#+BEGIN_SRC elisp
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
((go-mode (go-backend . go-mode)))
#+END_SRC
*Note:* you can easily add a directory local variable with ~SPC f v d~.
*** Debugger
Using the =dap= layer you'll get access to all the DAP key bindings, see the complete list of key bindings on the [[https://github.com/syl20bnr/spacemacs/tree/develop/layers/%2Btools/dap#key-bindings][dap layer description]].
* Working with Go
** Go commands (start with =m=):
| Key binding | Description |
|---------------+---------------------------------------------------------------------------------------|
| ~SPC m =~ | run "go fmt" |
| ~SPC m e b~ | go-play buffer |
| ~SPC m e d~ | download go-play snippet |
| ~SPC m e r~ | go-play region |
| ~SPC m g a~ | jump to matching test file or back from test to code file |
| ~SPC m g c~ | open a clone of the current buffer with a coverage info (=go tool cover -h= for help) |
| ~SPC m g g~ | go jump to definition |
| ~SPC m h h~ | godoc at point |
| ~SPC m i a~ | add import |
| ~SPC m i g~ | goto imports |
| ~SPC m i r~ | remove unused import |
| ~SPC m r n~ | go rename |
| ~SPC m t P~ | run "go test" for the current package and all packages under it |
| ~SPC m t g f~ | generate tests for all exported functions |
| ~SPC m t g F~ | generate tests for all functions |
| ~SPC m t g g~ | DWIM generate test for the function in the active region |
| ~SPC m t p~ | run "go test" for the current package |
| ~SPC m t s~ | run "go test" for the suite you're currently in (requires gocheck) |
| ~SPC m t t~ | run "go test" for the function you're currently in (while you're in a _.test.go file) |
| ~SPC m x x~ | run "go run" for the current 'main' package |
** Go Guru
| Key binding | Description |
|-------------+------------------------------------------------------|
| ~SPC m f <~ | go-guru show possible callers |
| ~SPC m f >~ | go-guru show call targets |
| ~SPC m f c~ | go-guru show channel sends/receives |
| ~SPC m f d~ | go-guru describe symbol at point |
| ~SPC m f e~ | go-guru show possible contants/types for error value |
| ~SPC m f f~ | go-guru show free variables |
| ~SPC m f i~ | go-guru show implements relation |
| ~SPC m f j~ | go-guru jump to symbol definition |
| ~SPC m f o~ | go-guru set analysis scope |
| ~SPC m f p~ | go-guru show what the select expression points to |
| ~SPC m f r~ | go-guru show referrers |
| ~SPC m f s~ | go-guru show callstack |
** Refactoring
| Key binding | Description |
|-------------+-----------------------------------------------------------------|
| ~SPC m r d~ | Add comment stubs |
| ~SPC m r e~ | Extract code as new function |
| ~SPC m r f~ | Add field tags (with =gomodifytags=) |
| ~SPC m r F~ | Remove field tags (with =gomodifytags=) |
| ~SPC m r i~ | Generate method stubs for implementing an interface (=go-impl=) |
| ~SPC m r n~ | Rename (with =godoctor=) |
| ~SPC m r N~ | Rename (with =go-rename=) |
| ~SPC m r s~ | Fill structure with default values (with =go-fillstruct=) |
| ~SPC m r t~ | Toggle declaration and assignment |