{"id":13479861,"url":"https://github.com/fatih/vim-go-tutorial","last_synced_at":"2025-03-27T10:30:50.291Z","repository":{"id":37734480,"uuid":"61632427","full_name":"fatih/vim-go-tutorial","owner":"fatih","description":"Tutorial for vim-go","archived":true,"fork":false,"pushed_at":"2018-10-10T23:39:34.000Z","size":200,"stargazers_count":2112,"open_issues_count":0,"forks_count":190,"subscribers_count":62,"default_branch":"master","last_synced_at":"2024-11-15T04:36:48.285Z","etag":null,"topics":["tutorial","vim","vim-go"],"latest_commit_sha":null,"homepage":"https://github.com/fatih/vim-go","language":"Vim script","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fatih.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-06-21T12:32:37.000Z","updated_at":"2024-11-10T13:50:57.000Z","dependencies_parsed_at":"2022-07-08T04:47:56.494Z","dependency_job_id":null,"html_url":"https://github.com/fatih/vim-go-tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatih%2Fvim-go-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatih%2Fvim-go-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatih%2Fvim-go-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatih%2Fvim-go-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fatih","download_url":"https://codeload.github.com/fatih/vim-go-tutorial/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245826723,"owners_count":20678848,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["tutorial","vim","vim-go"],"created_at":"2024-07-31T16:02:24.136Z","updated_at":"2025-03-27T10:30:49.965Z","avatar_url":"https://github.com/fatih.png","language":"Vim script","readme":"# Archived project. No maintenance. \n\nThis project is not maintained anymore and is archived. Feel free to fork and\nmake your own changes if needed. For more detail read my blog post: [Taking an indefinite sabbatical from my projects](https://arslan.io/2018/10/09/taking-an-indefinite-sabbatical-from-my-projects/)\n\nThanks to everyone for their valuable feedback and contributions.\n\n\n# vim-go-tutorial\n\nTutorial for vim-go. A simple tutorial on how to install and use vim-go.\n\n# Table of Contents\n\n1. [Quick Setup](#quick-setup)\n2. [Hello World](#hello-world)\n3. [Run it](#run-it)\n4. [Build it](#build-it)\n5. [Fix it](#fix-it)\n6. [Test it](#test-it)\n7. [Cover it](#cover-it)\n8. [Edit it](#edit-it)\n  * [Imports](#imports)\n  * [Text Objects](#text-objects)\n  * [Struct split\u0026join](#struct-split-and-join)\n  * [Snippets](#snippets)\n9. [Beautify it](#beautify-it)\n10. [Check it](#check-it)\n11. [Navigate it](#navigate-it)\n  * [Alternate files](#alternate-files)\n  * [Go to definition](#go-to-definition)\n  * [Move between functions](#move-between-functions)\n12. [Understand it](#understand-it)\n  * [Documentation Lookup](#documentation-lookup)\n  * [Identifier resolution](#identifier-resolution)\n  * [Identifier highlighting](#identifier-highlighting)\n  * [Dependencies and files](#dependencies-and-files)\n  * [Guru](#guru)\n13. [Refactor it](#refactor-it)\n  * [Rename identifiers](#rename-identifiers)\n  * [Extract function](#extract-function)\n14. [Generate it](#generate-it)\n  * [Method stubs implementing an interface](#method-stubs-implementing-an-interface)\n15. [Share it](#share-it)\n16. [HTML template](#html-template)\n\n# Quick Setup\n\nWe're going to use `vim-plug` to install vim-go. Feel free to use other plugin\nmanagers instead. We will create a minimal `~/.vimrc`, and add to it as we go along.\n\nFirst fetch and install `vim-plug` along with `vim-go`:\n\n```\ncurl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim\ngit clone https://github.com/fatih/vim-go.git ~/.vim/plugged/vim-go\n```\n\nCreate `~/.vimrc` with following content:\n\n```vim\ncall plug#begin()\nPlug 'fatih/vim-go', { 'do': ':GoInstallBinaries' }\ncall plug#end()\n```\n\nOr open Vim and execute `:GoInstallBinaries`. This is a `vim-go` command that\ninstalls all `vim-go` dependencies for you. It doesn't download pre compiled\nbinaries, instead it calls `go get` under the hood, so the binaries are all\ncompiled in your host machine (which is both safe and simplifies the\ninstallation process as we don't need to provide binaries for multiple\nplatforms). If you already have some of the dependencies (such as `guru`,\n`goimports`) call `:GoUpdateBinaries` to update the binaries. \n\nFor the tutorial, all our examples will be under\n`GOPATH/src/github.com/fatih/vim-go-tutorial/`. Please be sure you're inside\nthis folder. This will make it easy to follow the\ntutorial. If you already have a `GOPATH` set up just execute:\n\n```\ngo get github.com/fatih/vim-go-tutorial\n```\n\nOr create the folder, if necessary. \n\n\n# Hello World!\n\nOpen the `main.go` file from your terminal:\n\n```\nvim main.go\n```\n\nIt's a very basic file that prints `vim-go` to stdout.\n\n# Run it\n\nYou can easily run the file with `:GoRun %`. Under the hood it calls `go run` for\nthe current file. You should see that it prints `vim-go`.\n\nFor whole package run with `:GoRun`.\n\n# Build it\n\nReplace `vim-go` with `Hello Gophercon`. Let us compile the file instead of running it.\nFor this we have `:GoBuild`. If you call it, you should see this message: \n\n```\nvim-go: [build] SUCCESS\n```\n\nUnder the hood it calls `go build`, but it's a bit smarter. It does a couple of\nthings differently: \n\n* No binaries are created; you can call `:GoBuild` multiple times without\n  polluting your workspace.\n* It automatically `cd`s into the source package's directory\n* It parses any errors and shows them inside a quickfix list \n* It automatically detects the GOPATH and modifies it if needed (detects\n  projects such as `gb`, `Godeps`, etc..)\n* Runs async if used within Vim 8.0.xxx or NeoVim\n\n# Fix it\n\nLet's introduce two errors by adding two compile errors:\n\n```go\nvar b = foo()\n\nfunc main() {\n\tfmt.Println(\"Hello GopherCon\")\n\ta\n}\n```\n\nSave the file and call `:GoBuild` again. \n\nThis time the quickfix view will be opened. To jump between the errors you can\nuse `:cnext` and `:cprevious`. Let us fix the first error, save the\nfile and call `:GoBuild` again. You'll see the quickfix list is updated with a\nsingle error. Remove the second error as well, save the file and call\n`:GoBuild` again. Now because there are no more errors, vim-go automatically\ncloses the quickfix window for you.\n\nLet us improve it a little bit. Vim has a setting called `autowrite` that\nwrites the content of the file automatically if you call `:make`. vim-go also\nmakes use of this setting. Open your `.vimrc` and add the following:\n\n```\nset autowrite\n```\n\nNow you don't have to save your file anymore when you call `:GoBuild`.  If we\nreintroduce the two errors and call `:GoBuild`, we can now iterate much more\nquickly by only calling `:GoBuild`.\n\n`:GoBuild` jumps to the first error encountered. If you don't want to jump\nappend the `!` (bang) sign: `:GoBuild!`.\n\nIn all the `go` commands, such as `:GoRun`, `:GoInstall`, `:GoTest`, etc..,\nwhenever there is an error the quickfix window always will pop up.\n\n### vimrc improvements\n\n* You can add some shortcuts to make it easier to jump between errors in quickfix\nlist:\n\n```vi\nmap \u003cC-n\u003e :cnext\u003cCR\u003e\nmap \u003cC-m\u003e :cprevious\u003cCR\u003e\nnnoremap \u003cleader\u003ea :cclose\u003cCR\u003e\n```\n\n* I also use these shortcuts to build and run a Go program with `\u003cleader\u003eb` and\n`\u003cleader\u003er`:\n\n```vim\nautocmd FileType go nmap \u003cleader\u003eb  \u003cPlug\u003e(go-build)\nautocmd FileType go nmap \u003cleader\u003er  \u003cPlug\u003e(go-run)\n```\n\n* There are two types of error lists in Vim. One is called `location list` the\nother `quickfix`. Unfortunately the commands for each lists are different. So\n`:cnext` only works for `quickfix` list, for `location lists` you have to use\n`:lnext`. Some of the commands in `vim-go` open a location list, because\nlocation lists are associated with a window and each window can have a\nseparate list. This means you can have multiple windows, and multiple\nlocation lists, one for `Build`, one for `Check`, one for `Tests`, etc..\n\nSome people prefer to use only `quickfix` though. If you add the following to\nyour `vimrc` all lists will be of type `quickfix`:\n\n```vim\nlet g:go_list_type = \"quickfix\"\n```\n\n# Test it\n\nLet's write a simple function and a test for the function. Add the following:\n\n\n```go\nfunc Bar() string {\n\treturn \"bar\"\n}\n```\n\nOpen a new file called `main_test.go` (it doesn't matter how you open it, from\ninside Vim, a separate Vim session, etc.. it's up to you). Let us use the\ncurrent buffer and open it from Vim via `:edit main_test.go`.\n\nWhen you open the new file you notice something. The file automatically has the\npackage declaration added:\n\n```go\npackage main\n```\n\nThis is done by vim-go automatically. It detected that the file is inside a\nvalid package and therefore created a file based on the package name (in our\ncase the package name was `main`). If there are no files, vim-go automatically\npopulates the content with a simple main package.\n\nUpdate the test file with the following code:\n\n```go\npackage main\n\nimport (\n\t\"testing\"\n)\n\nfunc TestBar(t *testing.T) {\n\tresult := Bar()\n\tif result != \"bar\" {\n\t\tt.Errorf(\"expecting bar, got %s\", result)\n\t}\n}\n```\n\nCall `:GoTest`. You'll see the following message:\n\n```\nvim-go: [test] PASS\n```\n\n`:GoTest` calls `go test` under the hood. It has the same improvements\nwe have for `:GoBuild`. If there is any test error, a quickfix list is\nopened again and you can jump to it easily.\n\nAnother small improvement is that you don't have to open the test file itself.\nTry it yourself: open `main.go` and call `:GoTest`. You'll see the tests will\nbe run for you as well.\n\n`:GoTest` times out after 10 seconds by default. This is useful because Vim is\nnot async by default. You can change the timeout value with `let g:go_test_timeout = '10s'`\n\nWe have two more commands that make it easy to deal with test files. The first\none is `:GoTestFunc`. This only tests the function under your cursor.\nLet us change the content of the test file (`main_test.go`) to:\n\n```go\npackage main\n\nimport (\n\t\"testing\"\n)\n\nfunc TestFoo(t *testing.T) {\n\tt.Error(\"intentional error 1\")\n}\n\nfunc TestBar(t *testing.T) {\n\tresult := Bar()\n\tif result != \"bar\" {\n\t\tt.Errorf(\"expecting bar, got %s\", result)\n\t}\n}\n\nfunc TestQuz(t *testing.T) {\n\tt.Error(\"intentional error 2\")\n}\n```\n\nNow when we call `:GoTest` a quickfix window will open with two errors.\nHowever if go inside the `TestBar` function and call `:GoTestFunc`, you'll see\nthat our test passes!  This is really useful if you have a lot of tests that\ntake time and you only want to run certain tests.\n\nThe other test-related command is `:GoTestCompile`. Tests not only need to\npass with success, they must compile without any problems.\n`:GoTestCompile` compiles your test file, just like `:GoBuild` and opens a\nquickfix if there are any errors. This however **doesn't run** the tests. This\nis very useful if you have a large test which you're editing a lot. Call\n`:GoTestCompile` in the current test file, you should see the following:\n\n```\nvim-go: [test] SUCCESS \n```\n\n### vimrc improvements\n\n* As with `:GoBuild` we can add a mapping to easily call `:GoTest` with a key\ncombination. Add the following to your `.vimrc`:\n\n```vim\nautocmd FileType go nmap \u003cleader\u003et  \u003cPlug\u003e(go-test)\n```\n\nNow you can easily test your files via `\u003cleader\u003et`\n\n* Let's make building Go files simpler. First, remove the following mapping we added\n  previously:\n\n```vim\nautocmd FileType go nmap \u003cleader\u003eb  \u003cPlug\u003e(go-build)\n```\n\nWe're going to add an improved mapping. To make it seamless for\nany Go file we can create a simple Vim function that checks the type of the Go\nfile, and executes `:GoBuild` or `:GoTestCompile`.  Below is the helper function\nyou can add to your `.vimrc`:\n\n```vim\n\" run :GoBuild or :GoTestCompile based on the go file\nfunction! s:build_go_files()\n  let l:file = expand('%')\n  if l:file =~# '^\\f\\+_test\\.go$'\n    call go#test#Test(0, 1)\n  elseif l:file =~# '^\\f\\+\\.go$'\n    call go#cmd#Build(0)\n  endif\nendfunction\n\nautocmd FileType go nmap \u003cleader\u003eb :\u003cC-u\u003ecall \u003cSID\u003ebuild_go_files()\u003cCR\u003e\n```\n\nNow whenever you hit `\u003cleader\u003eb` it'll build either your Go file or it'll\ncompile your test files seamlessly.\n\n* By default the leader shortcut is defined as: `\\` I've mapped my leader to\n`,` as I find it more useful with the following setting (put this in the\nbeginning of .vimrc):\n\n```vim\nlet mapleader = \",\"\n```\n\nSo with this setting, we can easily build any test and non test files with `,b`.\n\n# Cover it\n\nLet's dive further into the world of tests. Tests are really important. Go\nhas a really great way of showing the coverage of your source code. vim-go\nmakes it easy to see the code coverage without leaving Vim in a very elegant\nway.\n\n\nLet's first change our `main_test.go` file back to:\n\n```go\npackage main\n\nimport (\n\t\"testing\"\n)\n\nfunc TestBar(t *testing.T) {\n\tresult := Bar()\n\tif result != \"bar\" {\n\t\tt.Errorf(\"expecting bar, got %s\", result)\n\t}\n}\n```\n\nAnd `main.go` to\n\n\n```go\npackage main\n\nfunc Bar() string {\n\treturn \"bar\"\n}\n\nfunc Foo() string {\n\treturn \"foo\"\n}\n\nfunc Qux(v string) string {\n\tif v == \"foo\" {\n\t\treturn Foo()\n\t}\n\n\tif v == \"bar\" {\n\t\treturn Bar()\n\t}\n\n\treturn \"INVALID\"\n}\n```\n\nNow let us call `:GoCoverage`. Under the hood this calls `go test -coverprofile\ntempfile`. It parses the lines from the profile and then dynamically changes\nthe syntax of your source code to reflect the coverage. As you see, because we\nonly have a test for the `Bar()` function, that is the only function that is\ngreen. \n\nTo clear the syntax highlighting you can call `:GoCoverageClear`. Let us add a\ntest case and see how the coverage changes. Add the following to `main_test.go`:\n\n```go\nfunc TestQuz(t *testing.T) {\n\tresult := Qux(\"bar\")\n\tif result != \"bar\" {\n\t\tt.Errorf(\"expecting bar, got %s\", result)\n\t}\n\n\tresult = Qux(\"qux\")\n\tif result != \"INVALID\" {\n\t\tt.Errorf(\"expecting INVALID, got %s\", result)\n\t}\n}\n```\n\nIf we call `:GoCoverage` again, you'll see that the `Quz` function is now\ntested as well and that it has a larger coverage. Call `:GoCoverageClear` again\nto clear the syntax highlighting.\n\nBecause calling `:GoCoverage` and `:GoCoverageClear` are used a lot together,\nthere is another command that makes it easy to call and clear the result. You\ncan also use `:GoCoverageToggle`. This acts as a toggle and shows the coverage,\nand when called again it clears the coverage.  It's up to your workflow how you\nwant to use them.\n\nFinally, if you don't like vim-go's internal view, you can also call\n`:GoCoverageBrowser`. Under the hood it uses `go tool cover` to create a HTML\npage and then opens it in your default browser. Some people like this more.\n\nUsing the `:GoCoverageXXX` commands does not create any kind of temporary files\nand doesn't pollute your workflow. So you don't have to deal with removing\nunwanted files every time.\n\n### vimrc improvements\n\nAdd the following to your `.vimrc`:\n\n```vim\nautocmd FileType go nmap \u003cLeader\u003ec \u003cPlug\u003e(go-coverage-toggle)\n```\n\nWith this you can easily call `:GoCoverageToggle` with `\u003cleader\u003ec`\n\n\n# Edit it\n\n### Imports\n\nLet us start with a sample `main.go` file:\n\n```go\npackage main\n\n     import \"fmt\"\n\nfunc main() {\n fmt.Println(\"gopher\"     )\n}\n```\n\nLet's start with something we know already. If we save the file, you'll see that\nit'll be formatted automatically. It's enabled by default but can be disabled\nif desired (not sure why you would though :)) with `let g:go_fmt_autosave = 0`.\nOptionally we also provide `:GoFmt` command, which runs `gofmt` under the hood.\n\nLet's print the `\"gopher\"` string in all uppercase. For it we're going to use\nthe `strings` package. Change the definition to:\n\n```go\nfmt.Println(strings.ToUpper(\"gopher\"))\n```\n\nWhen you build it you'll get an error of course:\n\n```\nmain.go|8| undefined: strings in strings.ToUpper\n```\n\nYou'll see we get an error because the `strings` package is not imported. vim-go\nhas a couple of commands to make it easy to manipulate the import declarations.\n\nWe can easily go and edit the file, but instead we're going to use the Vim\ncommand `:GoImport`. This command adds the given package to the import path.\nRun it via: `:GoImport strings`. You'll see the `strings` package is being\nadded.  The great thing about this command is that it also supports\ncompletion. So you can just type `:GoImport s` and hit tab.\n\nWe also have `:GoImportAs` and `:GoDrop` to edit the import paths.\n`:GoImportAs` is the same as `:GoImport`, but it allows changing the package\nname. For example `:GoImportAs str strings`, will import `strings` with the\npackage name `str.`\n\nFinally `:GoDrop` makes it easy to remove any import paths from the import\ndeclarations. `:GoDrop strings` will remove it from the import declarations.\n\nOf course manipulating import paths is so 2010. We have better tools to handle\nthis case for us. If you haven't heard yet, it's called `goimports`.\n`goimports` is a replacement for `gofmt`. You have two ways of using it. The\nfirst (and recommended) way is telling vim-go to use it when saving the\nfile:\n\n```\nlet g:go_fmt_command = \"goimports\"\n```\n\nNow whenever you save your file, `goimports` will automatically format and also\nrewrite your import declarations. Some people do not prefer `goimports` as it\nmight be slow on very large codebases. In this case we also have the\n`:GoImports` command (note the `s` at the end). With this, you can explicitly\ncall `goimports`\n\n\n### Text objects\n\nLet us show more editing tips/tricks. There are two text objects that we can\nuse to change functions. Those are `if` and `af`. `if` means inner function and\nit allows you to select the content of a function enclosure. Change your `main.go` file to:\n\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(1)\n\tfmt.Println(2)\n\tfmt.Println(3)\n\tfmt.Println(4)\n\tfmt.Println(5)\n}\n```\n\nPut your cursor on the `func` keyword  Now execute the following in `normal`\nmode and see what happens:\n\n```\ndif\n```\n\nYou'll see that the function body is removed. Because we used the `d` operator.\nUndo your changes with `u`. The great thing is that your cursor can be anywhere\nstarting from the `func` keyword until the closing right brace `}`. It uses the tool\n[motion](https://github.com/fatih/motion) under the hood. I wrote motion\nexplicitly for vim-go to support features like this. It's Go AST aware and thus\nits capabilities are really good. Like what you might ask? Change `main.go` to:\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc Bar() string {\n\tfmt.Println(\"calling bar\")\n\n\tfoo := func() string {\n\t\treturn \"foo\"\n\t}\n\n\treturn foo()\n}\n```\n\nPreviously we were using regexp-based text objects, which leads to problems.\nFor example in this example, put your cursor to the anonymous functions' `func`\nkeyword and execute `dif` in `normal` mode. You'll see that only the body of\nthe anonymous function is deleted.\n\nWe have only used the `d` operator (delete) so far. However it's up to you. For\nexample you can select it via `vif` or yank(copy) with `yif`.\n\nWe also have `af`, which means `a function`. This text object includes the\nwhole function declaration. Change your `main.go` to:\n\n\n```go\npackage main\n\nimport \"fmt\"\n\n// bar returns a the string \"foo\" even though it's named as \"bar\". It's an\n// example to be used with vim-go's tutorial to show the 'if' and 'af' text\n// objects.\nfunc bar() string {\n\tfmt.Println(\"calling bar\")\n\n\tfoo := func() string {\n\t\treturn \"foo\"\n\t}\n\n\treturn foo()\n}\n```\n\n\nSo here is the great thing. Because of `motion` we have full knowledge about\nevery single syntax node. Put your cursor on top of the `func`  keyword or\nanywhere below or above (doesn't matter). If you now execute `vaf`, you'll see\nthat the function declaration is being selected, along with the doc comment as\nwell! You can for example delete the whole function with `daf`, and you'll see\nthat the comment is gone as well. Go ahead and put your cursor on top of the\ncomment and execute `vif` and then `vaf`. You'll see that it selects the\nfunction body, even though your cursor is outside the function, or it selects\nthe function comments as well.\n\nThis is really powerful and this all is thanks to the knowledge we have from\n`let g:go_textobj_include_function_doc = 1` `motion`. If you don't like comments\nbeing a part of the function declaration, you can easily disable it with:\n\n```vim\nlet g:go_textobj_include_function_doc = 0\n```\n\nIf you are interested in learning more about `motion`, check out the blog post I wrote for\nmore details: [Treating Go types as objects in vim](https://medium.com/@farslan/treating-go-types-as-objects-in-vim-ed6b3fad9287#.45q2rtqgf)\n\n(Optional question: without looking at the `go/ast` package, is the doc comment\na part of the function declaration or not?)\n\n### Struct split and join\nThere is a great plugin that allows you to split or join Go structs. It's\nactually not a Go plugin, but it has support for Go structs. To enable it add\nplugin directive between the `plug` definition into your `vimrc`, then do a `:source ~/.vimrc` in your vim editor and run\n`:PlugInstall`. Example:\n\n```vim\ncall plug#begin()\nPlug 'fatih/vim-go'\nPlug 'AndrewRadev/splitjoin.vim'\ncall plug#end()\n```\n\nOnce you have installed the plugin, change the `main.go` file to:\n\n```go\npackage main\n\ntype Foo struct {\n\tName    string\n\tPorts   []int\n\tEnabled bool\n}\n\nfunc main() {\n\tfoo := Foo{Name: \"gopher\", Ports: []int{80, 443}, Enabled: true}\n}\n```\n\nPut your cursor on the same line as the struct expression. Now type `gS`. This\nwill `split` the struct expression into multiple lines. And you can even\nreverse it. If your cursor is still on the `foo` variable, execute `gJ` in\n`normal` mode. You'll see that the field definitions are all joined.\n\nThis doesn't use any AST-aware tools, so for example if you type `gJ` on top of\nthe fields, you'll see that only two fields are joined.\n\n### Snippets\n\nVim-go supports two popular snippet plugins.\n[Ultisnips](https://github.com/SirVer/ultisnips) and\n[neosnippet](https://github.com/Shougo/neosnippet.vim). By default, \nif you have `Ultisnips` installed it'll work.  Let us install `ultisnips`\nfirst. Add it between the `plug` directives in your `vimrc`, then do a `:source ~/.vimrc` in your vim editor and then run\n`:PlugInstall`. Example:\n\n```vim\ncall plug#begin()\nPlug 'fatih/vim-go'\nPlug 'SirVer/ultisnips'\ncall plug#end()\n```\n\nThere are many helpful snippets. To see the full list check our current\nsnippets:\nhttps://github.com/fatih/vim-go/blob/master/gosnippets/UltiSnips/go.snippets\n\n[UltiSnips and YouCompleteMe may conflict on [tab] button](https://stackoverflow.com/questions/14896327/ultisnips-and-youcompleteme)\n\n\nLet me show some of the snippets that I'm using the most. Change your `main.go`\ncontent to:\n\n```go\npackage main\n\nimport \"encoding/json\"\n\ntype foo struct {\n\tMessage    string\n\tPorts      []int\n\tServerName string\n}\n\nfunc newFoo() (*foo, error) {\n\treturn \u0026foo{\n\t\tMessage:  \"foo loves bar\",\n\t\tPorts: []int{80},\n\t\tServerName: \"Foo\",\n\t}, nil\n}\n\nfunc main() {\n\tres, err := newFoo()\n\n\tout, err := json.Marshal(res)\n}\n```\n\nLet's put our cursor just after the `newFoo()` expression. Let's panic here if\nthe err is non-nil. Type `errp` in insert mode and just hit `tab`. You'll see\nthat it'll be expanded and put your cursor inside the `panic()`` function:\n\n```\nif err != nil {\n    panic( )\n          ^\n          cursor position\n}\n```\n\nFill the panic with `err` and move on to the `json.Marshal` statement. Do the\nsame for it.\n\nNow let us print the variable `out`. Because variable printing is so popular,\nwe have several snippets for it:\n\n```\nfn -\u003e fmt.Println()\nff -\u003e fmt.Printf()\nln -\u003e log.Println()\nlf -\u003e log.Printf()\n```\n\nHere `ff` and `lf` are special. They dynamically copy the variable name into\nthe format string as well. Try it yourself. Move your cursor to the end of the\nmain function and type `ff` and hit tab. After expanding the snippet you can\nstart typing. Type `string(out)` and you'll see that both the format string and\nthe variadic arguments will be filled with the same string you have typed.\n\nThis comes very handy to quickly print variables for debugging.\nRun your file with `:GoRun` and you should see the following output:\n\n```\nstring(out) = {\"Message\":\"foo loves bar\",\"Ports\":[80],\"ServerName\":\"Foo\"}\n```\n\nGreat. Now let me show one last snippet that I think is very useful. As you see\nfrom the output the fields `Message` and `Ports` begin with uppercase\ncharacters. To fix it we can add a json tag to the struct field. vim-go makes it\nvery easy to add field tags. Move your cursor to the end of the `Message`\nstring line in the field:\n\n```\ntype foo struct {\n    Message string .\n                   ^ put your cursor here \n}\n```\n\nIn `insert` mode, type `json` and hit tab. You'll see that it'll be\nautomatically expanded to valid field tag. The field name is converted\nautomatically to a lowercase and put there for you. You should now see the\nfollowing:\n\n```\ntype foo struct {\n\tMessage  string `json:\"message\"`\n}\n```\n\nIt's really amazing. But we can do even better! Go ahead and create a\nsnippet expansion for the `ServerName` field. You'll see that it's converted to\n`server_name`. Amazing right?\n\n```go\ntype foo struct {\n\tMessage    string `json:\"message\"`\n\tPorts      []int\n\tServerName string `json:\"server_name\"`\n}\n```\n\n### vimrc improvements\n\n* Don't forget to change `gofmt` to `goimports`\n\n```vim\nlet g:go_fmt_command = \"goimports\"\n```\n\n* When you save your file, `gofmt` shows any errors during parsing the file. If\n  there are any parse errors it'll show them inside a quickfix list. This is\n  enabled by default. Some people don't like it. To disable it add:\n\n```vim\nlet g:go_fmt_fail_silently = 1\n```\n\n* You can change which case it should apply while converting. By default vim-go\n  uses `snake_case`. But you can also use `camelCase` if you wish. For example\n  if you wish to change the default value to camel case use the following\n  setting:\n\n```vim\nlet g:go_addtags_transform = \"camelcase\"\n```\n\n# Beautify it\n\nBy default we only have a limited syntax highlighting enabled. There are two\nmain reasons. First is that people don't like too much color because it causes\ntoo much distraction. The second reason is that it impacts\nthe performance of Vim a lot. We need to enable it explicitly. First add the\nfollowing settings to your `.vimrc`:\n\n```vim\nlet g:go_highlight_types = 1\n```\n\nThis highlights the `bar` and `foo` below:\n\n```\ntype foo struct{\n  quz string\n}\n\ntype bar interface{}\n```\n\nAdding the following:\n\n```vim\nlet g:go_highlight_fields = 1\n```\n\nWill highlight the `quz` below:\n\n```go\ntype foo struct{\n  quz string\n}\n\n\nf := foo{quz:\"QUZ\"}\nf.quz # quz here will be highlighted\n```\n\nIf we add the following:\n\n```vim\nlet g:go_highlight_functions = 1\n```\n\nWe are now also highlighting function and method names in declarations. `Foo`\nand `main` will now be highlighted, but `Println` is not as that is an\ninvocation:\n\n```go\nfunc (t *T) Foo() {}\n\nfunc main() {\n  fmt.Println(\"vim-go\")\n}\n```\n\nIf you also want to highlight function and method invocations, add the\nfollowing:\n\n```vim\nlet g:go_highlight_function_calls = 1\n```\n\nNow, `Println` will also be highlighted:\n\n```go\nfunc (t *T) Foo() {}\n\nfunc main() {\n  fmt.Println(\"vim-go\")\n}\n```\n\nIf you add `let g:go_highlight_operators = 1` it will highlight the following\noperators such as:\n\n```\n- + % \u003c \u003e ! \u0026 | ^ * =\n-= += %= \u003c= \u003e= != \u0026= |= ^= *= ==\n\u003c\u003c \u003e\u003e \u0026^\n\u003c\u003c= \u003e\u003e= \u0026^=\n:= \u0026\u0026 || \u003c- ++ --\n```\n\nIf you add `let g:go_highlight_extra_types = 1` the following extra types\nwill be highlighted as well:\n\n```\nbytes.(Buffer)\nio.(Reader|ReadSeeker|ReadWriter|ReadCloser|ReadWriteCloser|Writer|WriteCloser|Seeker)\nreflect.(Kind|Type|Value)\nunsafe.Pointer\n```\n\nLet's move on to more useful highlights. What about build tags? It's not easy\nto implement it without looking into the `go/build` document. Let us first add\nthe following: `let g:go_highlight_build_constraints = 1` and change your\n`main.go` file to:\n\n```\n// build linux\npackage main\n```\n\nYou'll see that it's gray, thus it's not valid. Prepend `+` to the `build` word and save it again:\n\n```\n// +build linux\npackage main\n```\n\nDo you know why? If you read the `go/build` package you'll see that the\nfollowing is buried in the document:\n\n\u003e ... preceded only by blank lines and other line comments.\n\nLet us change our content again and save it to:\n\n\n```\n// +build linux\n\npackage main\n```\n\nYou'll see that it automatically highlighted it in a valid way. It's really\ngreat. If you go and change `linux` to something you'll see that it also checks\nfor valid official tags (such as `darwin`,`race`, `ignore`, etc... )\n\n\nAnother similar feature is to highlight the Go directive `//go:generate`. If\nyou put `let g:go_highlight_generate_tags = 1` into your vimrc, it'll highlight\na valid directive that is processed with the `go generate` command.\n\nWe have a lot more highlight settings, these are just a sneak peek of it. For\nmore check out the settings via `:help go-settings`\n\n\n### vimrc improvements\n\n* Some people don't like how the tabs are shown. By default Vim shows `8`\n  spaces for a single tab. However it's up to us how to represent in Vim. The\n  following will change it to show a single tab as 4 spaces:\n\n```\nautocmd BufNewFile,BufRead *.go setlocal noexpandtab tabstop=4 shiftwidth=4 \n```\n\nThis setting will not expand a tab into spaces. It'll show a single tab as `4`\nspaces. It will use `4` spaces to represent a single indent.\n\n* A lot of people ask for my colorscheme. I'm using a slightly modified\n`molokai`. To enable it add the Plug directive just between the plug\ndefinitions:\n\n```vim\ncall plug#begin()\nPlug 'fatih/vim-go'\nPlug 'fatih/molokai'\ncall plug#end()\n```\n\nAlso add the following to enable molokai with original color scheme and 256\ncolor version:\n\n```vim\nlet g:rehash256 = 1\nlet g:molokai_original = 1\ncolorscheme molokai\n```\n\nAfter that restart Vim and call `:source ~/.vimrc`, then `:PlugInstall`. This will pull the plugin\nand install it for you. After the plugin is installed, you need to restart Vim\nagain.\n\n# Check it\n\nFrom the previous examples you saw that we had many commands that would show\nthe quickfix window when there was an issue. For example `:GoBuild` shows\nerrors from the compile output (if any). Or for example `:GoFmt` shows the\nparse errors of the current file while formatting it.\n\nWe have many other commands that allows us to call and then collect errors,\nwarnings or suggestions.\n\nFor example `:GoLint`. Under the hood it calls `golint`, which is a command\nthat suggests changes to make Go code more idiomatic. There\nis also `:GoVet`, which calls `go vet` under the hood. There are many other\ntools that check certain things. To make it easier, someone decided to\ncreate a tool that calls all these checkers. This tool is called\n`gometalinter`. And vim-go supports it via the command `:GoMetaLinter`. So what\ndoes it do?\n\nIf you just call `:GoMetaLinter` for a given Go source code. By default it'll run\n`go vet`, `golint` and `errcheck` concurrently. `gometalinter` collects\nall the outputs and normalizes it to a common format. Thus if you call\n`:GoMetaLinter`, vim-go shows the result of all these checkers inside a\nquickfix list. You can then jump easily between the lint, vet and errcheck\nresults. The setting for this default is as following:\n\n```vim\nlet g:go_metalinter_enabled = ['vet', 'golint', 'errcheck']\n```\n\nThere are many other tools and you can easily customize this list yourself. If\nyou call `:GoMetaLinter` it'll automatically uses the list above.\n\n\nBecause `:GoMetaLinter` is usually fast, vim-go also can call it whenever you\nsave a file (just like `:GoFmt`). To enable it you need to add the following to\nyour `.vimrc:`\n\n```vim\nlet g:go_metalinter_autosave = 1\n```\n\nWhat's great is that the checkers for the autosave is different than what you\nwould use for `:GoMetaLinter`.  This is great because you can customize it so only\nfast checkers are called when you save your file, but others if you call\n`:GoMetaLinter`. The following setting let you customize the checkers for the\n`autosave` feature.\n\n\n```vim\nlet g:go_metalinter_autosave_enabled = ['vet', 'golint']\n```\n\nAs you see by default `vet` and `golint` are enabled. Lastly, to prevent\n`:GoMetaLinter` running for too long, we have a setting to cancel it after a\ngiven timeout. By default it is `5 seconds` but can be changed by the following\nsetting:\n\n```vim\nlet g:go_metalinter_deadline = \"5s\"\n```\n\n# Navigate it\n\nSo far we have only jumped between two files, `main.go` and `main_test.go`. It's\nreally easy to switch if you have just two files in the same directory. But\nwhat if the project gets larger and larger with time? Or what if the file\nitself is so large that you have hard time navigating it?\n\n\n### Alternate files\n\nvim-go has several ways of improving navigation. First let me\nshow how we can quickly jump between a Go source code and its test file.\n\nSuppose you have both a `foo.go` and its equivalent test file `foo_test.go`.\nIf you have `main.go` from the previous examples with its test file you can\nalso open it. Once you open it just execute the following Vim command:\n\n```vim\n:GoAlternate\n```\n\nYou'll see that you switched immediately to `main_test.go`. If you execute it\nagain, it'll switch to `main.go`. `:GoAlternate` works as a toggle and is\nreally useful if you have a package with many test files.  The idea is very\nsimilar to the plugin [a.vim](https://github.com/vim-scripts/a.vim) command\nnames. This plugin jumps between a `.c` and `.h` file. In our case\n`:GoAlternate` is used to switch between a test and non-test file.\n\n### Go to definition\n\nOne of the most used features is `go to definition`. From the beginning, vim-go \nhad the `:GoDef` command that jumps to any identifier's declaration. Let\nus first create a `main.go` file to show it in action. Create it with the\nfollowing content:\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype T struct {\n\tFoo string\n}\n\nfunc main() {\n\tt := T{\n\t\tFoo: \"foo\",\n\t}\n\n\tfmt.Printf(\"t = %+v\\n\", t)\n}\n```\n\nNow we have here several ways of jumping to declarations. For example if you put\nyour cursor on top of `T` expression just after the main function and call\n`:GoDef` it'll jump to the type declaration.\n\nIf you put your cursor on top of the `t` variable declaration just after the\nmain function and call `:GoDef`, you'll see that nothing will happen. Because\nthere is no place to go, but if you scroll down a few lines and put your cursor\nto the `t` variable used in `fmt.Printf()` and call `:GoDef`, you'll see that\nit jumped to the variable declaration.\n\n`:GoDef` not only works for local scope, it works also globally\n(across`GOPATH`).  If, for example, you put your cursor on top of the `Printf()`\nfunction and call `:GoDef`, it'll jump directly to the `fmt` package.  Because\nthis is used so frequently, vim-go overrides the built in Vim shortcuts `gd`\nand `ctrl-]` as well. So instead of `:GoDef` you can easily use `gd` or\n`ctrl-]`\n\nOnce we jump to a declaration, we also might want to get back into our previous\nlocation. By default there is the Vim shortcut  `ctrl-o` that jumps to the\nprevious cursor location. It works great when it does, but not good enough if\nyou're navigating between Go declarations. If, for example, you jump to a file\nwith `:GoDef` and then scroll down to the bottom, and then maybe to the top,\n`ctrl-o` will remember these locations as well. So if you want to jump back to\nthe previous location when invoking `:GoDef`, you have to hit `ctrl-o` multiple\ntimes. And this is really annoying.\n\nWe don't need to use this shortcut though, as vim-go has a better implementation\nfor you. There is a command `:GoDefPop` which does exactly this. vim-go\nkeeps an internal stack list for all the locations you visit with `:GoDef`.\nThis means you can jump back easily again via `:GoDefPop` to your older\nlocations, and it works even if you scroll down/up in a file. And because this\nis also used so many times we have the shortcut `ctrl-t` which calls under the\nhood `:GoDefPop`. So to recap:\n\n* Use `ctrl-]` or `gd` to jump to a definition, locally or globally\n* Use `ctrl-t` to jump back to the previous location \n\nLet us move on with another question, suppose you jump so far that you just\nwant to back to where you started? As mentioned earlier,\nvim-go keeps an history of all your locations invoked via `:GoDef`. There is a\ncommand that shows all these and it's called `:GoDefStack`. If you call it,\nyou'll see that a custom window with a list of your old locations will be\nshown. Just navigate to your desired location and hit enter.  And finally to\nclear the stack list anytime call `:GoDefStackClear`.\n\n\n### Move between functions\n\nFrom the previous example we see that `:GoDef` is nice if you know where you want to\njump. But what if you don't know what your next destination is? Or you just\npartially know the name of a function? \n\nIn our `Edit it` section I mentioned a tool called `motion`, which is a\ncustom built tool just for vim-go. `motion` has other capabilities as well.\n`motion` parses your Go package and thus has a great understanding of all\ndeclarations. We can take advantage of this feature for jumping between\ndeclarations. There are two commands, which are not available until you install\na certain plugin. The commands are:\n\n```\n:GoDecls\n:GoDeclsDir\n```\n\nFirst let us enable these two commands by installing the necessary plugin. The\nplugin is called [ctrlp](https://github.com/ctrlpvim/ctrlp.vim). Long-time Vim\nusers have it installed already. To install it add the following line between\nyour `plug` directives, then do a `:source ~/.vimrc` in your vim editor and call `:PlugInstall` to install it:\n\n```vim\nPlug 'ctrlpvim/ctrlp.vim'\n```\n\nOnce you have it installed, use the following `main.go` content:\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype T struct {\n\tFoo string\n}\n\nfunc main() {\n\tt := T{\n\t\tFoo: \"foo\",\n\t}\n\n\tfmt.Printf(\"t = %+v\\n\", t)\n}\n\nfunc Bar() string {\n\treturn \"bar\"\n}\n\nfunc BarFoo() string {\n\treturn \"bar_foo\"\n}\n```\n\nAnd a `main_test.go` file with the following content:\n\n```go\npackage main\n\nimport (\n\t\"testing\"\n)\n\ntype files interface{}\n\nfunc TestBar(t *testing.T) {\n\tresult := Bar()\n\tif result != \"bar\" {\n\t\tt.Errorf(\"expecting bar, got %s\", result)\n\t}\n}\n\nfunc TestQuz(t *testing.T) {\n\tresult := Qux(\"bar\")\n\tif result != \"bar\" {\n\t\tt.Errorf(\"expecting bar, got %s\", result)\n\t}\n\n\tresult = Qux(\"qux\")\n\tif result != \"INVALID\" {\n\t\tt.Errorf(\"expecting INVALID, got %s\", result)\n\t}\n}\n```\n\nOpen `main.go` and call `:GoDecls`. You'll see that `:GoDecls` shows all type\nand function declarations for you. If you type `ma` you'll see that `ctrlp`\nfilters the list for you. If you hit `enter` it will automatically jump to it.\nThe fuzzy search capabilities combined with `motion`'s AST capabilities brings\nus a very simple to use but powerful feature.\n\nFor example, call `:GoDecls` and write `foo`. You'll see that it'll filter\n`BarFoo` for you. The Go parser is very fast and works very well with large files\nwith hundreds of declarations.\n\nSometimes just searching within the current file is not enough. A Go package can\nhave multiple files (such as tests). A type declaration can be in one file,\nwhereas a some functions specific to a certain set of features can be in\nanother file. This is where `:GoDeclsDir` is useful. It parses the whole\ndirectory for the given file and lists all the declarations from the files in the \ngiven directory (but not subdirectories).\n\nCall `:GoDeclsDir`. You'll see this time it also included the declarations from\nthe `main_test.go` file as well. If you type `Bar`, you'll see both the `Bar`\nand `TestBar` functions. This is really great if you just want to get an\noverview of all type and function declarations, and also jump to them.\n\nLet's continue with a question. What if you just want to move to the next or\nprevious function? If your current function body is long, you'll probably will\nnot see the function names. Or maybe there are other declarations between the\ncurrent and other functions.\n\nVim already has motion operators like `w` for words or `b` for backwards words.\nBut what if we could add motions for Go ast? For example for function declarations?\n\nvim-go provides(overrides) two motion objects to move between functions. These\nare:\n\n\n```\n]] -\u003e jump to next function\n[[ -\u003e jump to previous function\n```\n\nVim has these shortcuts by default. But those are suited for C source code and\njumps between braces. We can do it better. Just like our previous example,\n`motion` is used under the hood for this operation\n\nOpen `main.go` and move to the top of the file. In `normal` mode, type `]]` and\nsee what happens. You'll see that you jumped to the `main()` function. Another\n`]]` will jump to `Bar()` If you hit `[[` it'll jump back to the `main()`\nfunction.\n\n`]]` and `[[` also accepts `counts`. For example if you move to the top again\nand hit `3]]` you'll see that it'll jump to the third function in the source file.\nAnd going forward, because these are valid motions, you can apply operators to\nit as well!\n\nIf you move your file to the top  and hit `d]]` you'll see that it deleted\nanything before the next function. For example one useful usage would be typing\n`v]]` and then hit `]]` again to select the next function, until you've done\nwith your selection.\n\n\n### .vimrc improvements\n\n* We can improve it to control how it opens the alternate file. Add the\n  following to your `.vimrc`:\n\n\n```vim\nautocmd Filetype go command! -bang A call go#alternate#Switch(\u003cbang\u003e0, 'edit')\nautocmd Filetype go command! -bang AV call go#alternate#Switch(\u003cbang\u003e0, 'vsplit')\nautocmd Filetype go command! -bang AS call go#alternate#Switch(\u003cbang\u003e0, 'split')\nautocmd Filetype go command! -bang AT call go#alternate#Switch(\u003cbang\u003e0, 'tabe')\n```\n\nThis will add new commands, called `:A`, `:AV`, `:AS` and `:AT`. Here `:A`\nworks just like `:GoAlternate`, it replaces the current buffer with the\nalternate file. `:AV` will open a new vertical split with the alternate file.\n`:AS` will open the alternate file in a new split view and `:AT` in a new tab.\nThese commands are very productive depending on how you use them, so I think\nit's useful to have them.\n\n* The \"go to definition\" command families are very powerful but yet easy to use.\nUnder the hood it uses by default the tool `guru` (formerly `oracle`). `guru` has\nan excellent track record of being very predictable. It works for dot imports,\nvendorized imports and many other non-obvious identifiers. But sometimes it's\nvery slow for certain queries. Previously vim-go was using `godef` which is\nvery fast on resolving queries. With the latest release one can easily use or\nswitch the underlying tool for `:GoDef`.  To change it back to `godef` use the\nfollowing setting:\n\n```vim\nlet g:go_def_mode = 'godef'\n```\n\n* Currently by default `:GoDecls` and `:GoDeclsDir` show type and function\n  declarations. This is customizable with the `g:go_decls_includes` setting. By\n  default it's in the form of:\n\n```\nlet g:go_decls_includes = \"func,type\"\n```\n\nIf you just want to show function declarations, change it to:\n\n```\nlet g:go_decls_includes = \"func\"\n```\n\n# Understand it\n\nWriting/editing/changing code is usually something we can do only if we first\nunderstand what the code is doing. vim-go has several ways to make it easy to\nunderstand what your code is all about. \n\n### Documentation lookup\n\nLet's start with the basics. Go documentation is very well-written and is\nhighly integrated into the Go AST as well. If you just write some comments, the\nparser can easily parse it and associate with any node in the AST. So what it\nmeans is that we can easily find the documentation in the reverse order. If\nyou have the node from an AST, you can easily read the documentation (if you\nhave it)!\n\nWe have a command called `:GoDoc` that shows any documentation associated with\nthe identifier under your cursor. Let us change the content of `main.go` to:\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n\tfmt.Println(sayHi())\n\tfmt.Println(sayYoo())\n}\n\n// sayHi() returns the string \"hi\"\nfunc sayHi() string {\n\treturn \"hi\"\n}\n\nfunc sayYoo() string {\n\treturn \"yoo\"\n}\n```\n\nPut your cursor on top of the `Println` function just after the `main` function\nand call `:GoDoc`. You'll see that it vim-go automatically opens a scratch\nwindow that shows the documentation for you:\n\n```\nimport \"fmt\"\n\nfunc Println(a ...interface{}) (n int, err error)\n\nPrintln formats using the default formats for its operands and writes to\nstandard output. Spaces are always added between operands and a newline is\nappended. It returns the number of bytes written and any write error\nencountered.\n```\n\nIt shows the import path, the function signature and then finally the doc\ncomment of the identifier. Initially vim-go was using plain `go doc`, but it\nhas some shortcomings, such as not resolving based on a byte identifier. `go\ndoc` is great for terminal usages, but it's hard to integrate into editors.\nFortunately we have a very useful tool called `gogetdoc`, which resolves and\nretrieves the AST node for the underlying node and outputs the associated doc\ncomment.\n\nThat's why `:GoDoc` works for any kind of identifier. If you put your cursor under\n`sayHi()` and call `:GoDoc` you'll see that it shows it as well. And if you put\nit under `sayYoo()` you'll see that it just outputs `no documentation` for AST\nnodes without doc comments.\n\nAs usual with other features, we override the default normal shortcut `K` so\nthat it invokes `:GoDoc` instead of `man` (or something else). It's really easy\nto find the documentation, just hit `K` in normal mode!\n\n`:GoDoc` just shows the documentation for a given identifier. But it's not a\n**documentation explorer**, if you want to explore the documentation there is\nthird-party plugin that does it:\n[go-explorer](https://github.com/garyburd/go-explorer). There is an open bug to\ninclude it into vim-go.\n\n### Identifier resolution\n\nSometimes you want to know what a function is accepting or returning. Or what\nthe identifier under your cursor is. Questions like this are common and we have\na command to answer it.\n\nUsing the same `main.go` file, go over the `Println` function and call\n`:GoInfo`. You'll see that the function signature is being printed in the\nstatus line. This is really great to see what it's doing, as you don't have to\njump to the definition and check out what the signature is. \n\nBut calling `:GoInfo` every time is tedious. We can make some improvements to\ncall it faster. As always a way of making it faster is to add a shortcut:\n\n```vim\nautocmd FileType go nmap \u003cLeader\u003ei \u003cPlug\u003e(go-info)\n```\n\nNow you easily call `:GoInfo` by just hitting `\u003cleader\u003ei`. But there is still\nroom to improve it. vim-go has a support to automatically show the information\nwhenever you move your cursor. To enable it add the following to your `.vimrc`:\n\n```vim\nlet g:go_auto_type_info = 1\n```\n\nNow whenever you move your cursor onto a valid identifier, you'll see that your\nstatus line is updated automatically. By default it updates every `800ms`. This\nis a vim setting and can be changed with the `updatetime` setting. To change it\nto `100ms` add the following to your `.vimrc`\n\n```vim\nset updatetime=100\n```\n\n### Identifier highlighting\n\nSometimes we just want to quickly see all matching identifiers. Such as variables,\nfunctions, etc.. Suppose you have the following Go code:\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n\terr := sayHi()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\n// sayHi() returns the string \"hi\"\nfunc sayHi() error {\n\tfmt.Println(\"hi\")\n\treturn nil\n}\n```\n\nIf you put your cursor on top of `err` and call `:GoSameIds` you'll see that\nall the `err` variables get highlighted. Put your cursor on the `sayHi()`\nfunction call, and you'll see that the `sayHi()` function identifiers all are\nhighlighted. To clear them just call `:GoSameIdsClear`\n\nThis is more useful if we don't have to call it manually every time. vim-go\ncan automatically highlight matching identifiers. Add the following to your\n`vimrc`:\n\n```vim\nlet g:go_auto_sameids = 1\n```\n\nAfter restarting vim, you'll see that you don't need to call\n`:GoSameIds` manually anymore. Matching identifier variables are now highlighted\nautomatically for you.\n\n### Dependencies and files\n\nAs you know a package can consist of multiple dependencies and files. Even\nif you have many files inside the directory, only the files that have the\npackage clause correctly are part of a package.\n\nTo see the files that make a package you can call the following:\n\n```\n:GoFiles\n```\n\nwhich will output (my `$GOPATH` is set to `~/Code/Go`):\n\n```\n['/Users/fatih/Code/go/src/github.com/fatih/vim-go-tutorial/main.go']\n```\n\nIf you have other files those will be listed as well. Note that this command is\nonly for listing Go files that are part of the build. Test files will be not\nlisted. \n\nFor showing the dependencies of a file you can call `:GoDeps`. If you call  it\nyou'll see:\n\n```\n['errors', 'fmt', 'internal/race', 'io', 'math', 'os', 'reflect', 'runtime',\n'runtime/internal/atomic', 'runtime/internal/sys', 'strconv', 'sync',\n'sync/atomic ', 'syscall', 'time', 'unicode/utf8', 'unsafe']\n```\n\n### Guru\n\nThe previous feature was using the `guru` tool under the hood. So let's talk a\nlittle bit about guru. So what is guru? Guru is an editor integrated tool for\nnavigating and understanding Go code. There is a user manual that shows all the\nfeatures: [https://golang.org/s/using-guru](https://golang.org/s/using-guru)\n\n---\n\nLet us use the same examples from that manual to show some of the features we've\nintegrated into vim-go:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n)\n\nfunc main() {\n\th := make(handler)\n\tgo counter(h)\n\tif err := http.ListenAndServe(\":8000\", h); err != nil {\n\t\tlog.Print(err)\n\t}\n}\n\nfunc counter(ch chan\u003c- int) {\n\tfor n := 0; ; n++ {\n\t\tch \u003c- n\n\t}\n}\n\ntype handler chan int\n\nfunc (h handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {\n\tw.Header().Set(\"Content-type\", \"text/plain\")\n\tfmt.Fprintf(w, \"%s: you are visitor #%d\", req.URL, \u003c-h)\n}\n```\n\nPut your cursor on top of the `handler` and call `:GoReferrers`. This calls the\n`referrers` mode of `guru`, which finds references to the selected identifier,\nscanning all necessary packages within the workspace. The result will be a\nlocation list.\n\n---\n\nOne of the modes of `guru` is also the `describe` mode. It's just like\n`:GoInfo`, but it's a little bit more advanced (it gives us more information).\nIt shows for example the method set of a type if there is any. It shows the\ndeclarations of a package if selected.\n\nLet's continue with same `main.go` file.  Put the cursor on top of the `URL`\nfield or `req.URL` (inside the `ServeHTTP` function). Call `:GoDescribe`.  You'll\nsee a location list populated with the following content:\n\n```\nmain.go|27 col 48| reference to field URL *net/url.URL\n/usr/local/go/src/net/http/request.go|91 col 2| defined here\nmain.go|27 col 48| Methods:\n/usr/local/go/src/net/url/url.go|587 col 15| method (*URL) EscapedPath() string\n/usr/local/go/src/net/url/url.go|844 col 15| method (*URL) IsAbs() bool\n/usr/local/go/src/net/url/url.go|851 col 15| method (*URL) Parse(ref string) (*URL, error)\n/usr/local/go/src/net/url/url.go|897 col 15| method (*URL) Query() Values\n/usr/local/go/src/net/url/url.go|904 col 15| method (*URL) RequestURI() string\n/usr/local/go/src/net/url/url.go|865 col 15| method (*URL) ResolveReference(ref *URL) *URL\n/usr/local/go/src/net/url/url.go|662 col 15| method (*URL) String() string\nmain.go|27 col 48| Fields:\n/usr/local/go/src/net/url/url.go|310 col 2| Scheme   string\n/usr/local/go/src/net/url/url.go|311 col 2| Opaque   string\n/usr/local/go/src/net/url/url.go|312 col 2| User     *Userinfo\n/usr/local/go/src/net/url/url.go|313 col 2| Host     string\n/usr/local/go/src/net/url/url.go|314 col 2| Path     string\n/usr/local/go/src/net/url/url.go|315 col 2| RawPath  string\n/usr/local/go/src/net/url/url.go|316 col 2| RawQuery string\n/usr/local/go/src/net/url/url.go|317 col 2| Fragment string\n```\n\nYou'll see that we can see the definition of the field, the method set and the\n`URL` struct's fields. This is a very useful command and it's there if you need\nit and want to understand the surrounding code. Try and experiment by calling\n`:GoDescribe` on various other identifiers to see what the output is.\n\n---\n\nOne of the most asked questions is how to know the interfaces a type is\nimplementing. Suppose you have a type and with a method set of several methods.\nYou want to know which interface it might implement. The mode `implement` of\n`guru` just does it and it helps to find the interface a type implements.\n\nJust continue with the same previous `main.go` file. Put your cursor on the\n`handler` identifier just after the `main()` function. Call `:GoImplements`\nYou'll see a location list populated with the following content:\n\n\n```\nmain.go|23 col 6| chan type handler\n/usr/local/go/src/net/http/server.go|57 col 6| implements net/http.Handler\n```\n\nThe first line is our selected type and the second line will be the interface\nit implements. Because a type can implement many interfaces it's a location\nlist.\n\n---\n\nOne of the `guru` modes that might be helpful is `whicherrs`. As you know\nerrors are just values. So they can be programmed and thus can represent any\ntype. See what the `guru` manual says:\n\n\u003e The whicherrs mode reports the set of possible constants, global variables,\n\u003e and concrete types that may appear in a value of type error. This information\n\u003e may be useful when handling errors to ensure all the important cases have\n\u003e been dealt with.\n\nSo how do we use it? It's easy. We still use the same `main.go` file. Put your\ncursor on top of the `err` identifier which is returned from `http.ListenAndServe`.\nCall `:GoWhicherrs` and you'll see the following output:\n\n```\nmain.go|12 col 6| this error may contain these constants:\n/usr/local/go/src/syscall/zerrors_darwin_amd64.go|1171 col 2| syscall.EINVAL\nmain.go|12 col 6| this error may contain these dynamic types:\n/usr/local/go/src/syscall/syscall_unix.go|100 col 6| syscall.Errno\n/usr/local/go/src/net/net.go|380 col 6| *net.OpError\n```\n\nYou'll see that the `err` value may be the `syscall.EINVAL` constant or it also\nmight be the dynamic types `syscall.Errno` or `*net.OpError`. As you see this is\nreally helpful when implementing custom logic to handle the error differently if\nneeded. Note that this query needs a guru `scope` to be set. We'll going to\ncover in a moment what a `scope` is and how you can change it dynamically.\n\n---\n\nLet's continue with the same `main.go` file.  Go is famous for its concurrency\nprimitives, such as channels. Tracking how values are sent between channels can\nsometimes be hard. To understand it better we have the `peers` mode of `guru`.\nThis query shows the set of possible send/receives on the channel operand (send\nor receive operation).\n\nMove your cursor to the following expression and select the whole line:\n\n```go\nch \u003c- n\n```\n\nCall `:GoChannelPeers`. You'll see a location list window with the following content:\n\n```\nmain.go|19 col 6| This channel of type chan\u003c- int may be:\nmain.go|10 col 11| allocated here\nmain.go|19 col 6| sent to, here\nmain.go|27 col 53| received from, here\n```\n\nAs you see you can see the allocation of the channel, where it's sending and\nreceiving from. Because this uses pointer analysis, you have to define a scope.\n\n---\n\n\nLet us see how function calls and targets are related. This time create the\nfollowing files. The content of `main.go` should be:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/fatih/vim-go-tutorial/example\"\n)\n\nfunc main() {\n\tHello(example.GopherCon)\n\tHello(example.Kenya)\n}\n\nfunc Hello(fn func() string) {\n\tfmt.Println(\"Hello \" + fn())\n}\n```\n\nAnd the file should be under `example/example.go`:\n\n```go\npackage example\n\nfunc GopherCon() string {\n\treturn \"GopherCon\"\n}\n\nfunc Kenya() string {\n\treturn \"Kenya\"\n}\n```\n\nSo jump to the `Hello` function inside `main.go` and put your cursor on top of\nthe function call named `fn()`. Execute `:GoCallees`. This command shows the\npossible call targets of the selected function call. As you see it'll show us\nthe function declarations inside the `example` function. Those functions are\nthe callees, because they were called by the function call named `fn()`.\n\nJump back to `main.go` again and this time put your cursor on the function\ndeclaration `Hello()`. What if we want to see the callers of this function?\nExecute `:GoCallers`.\n\nYou should see the output:\n\n```\nmain.go| 10 col 7 static function call from github.com/fatih/vim-go-tutorial.Main\nmain.go| 11 col 7 static function call from github.com/fatih/vim-go-tutorial.Main\n```\n\nFinally there is also the `callstack` mode, which shows an arbitrary path from\nthe root of the call graph to the function containing the selection.\n\n\nPut your cursor back to the `fn()` function call inside the `Hello()` function.\nSelect the function and call `:GoCallstack`. The output should be like\n(simplified form):\n\n```\nmain.go| 15 col 26 Found a call path from root to (...)Hello\nmain.go| 14 col 5 (...)Hello\nmain.go| 10 col 7 (...)main\n```\nIt starts from line `15`, and then to line `14` and then ends at line `10`.\nThis is the graph from the root (which starts from `main()`) to the function we\nselected (in our case `fn()`)\n\n---\n\nFor most of the `guru` commands you don't need to define any scope. What is a\n`scope`? The following excerpt is straight from the `guru`\n[manual](http://golang.org/s/using-guru):\n\n\n\u003e Pointer analysis scope: some queries involve pointer analysis, a technique for\n\u003e answering questions of the form “what might this pointer point to?”.  It is\n\u003e usually too expensive to run pointer analysis over all the packages in the\n\u003e workspace, so these queries require an additional configuration parameter\n\u003e called the scope, which determines the set of packages to analyze.  Set the\n\u003e scope to the application (or set of applications---a client and server,\n\u003e perhaps) on which you are currently working.  Pointer analysis is a\n\u003e whole-program analysis, so the only packages in the scope that matter are the\n\u003e main and test packages.\n\u003e \n\u003e The scope is typically specified as a comma-separated set of packages, or\n\u003e wildcarded subtrees like github.com/my/dir/...; consult the specific\n\u003e documentation for your editor to find out how to set and vary the scope.\n\n\n`vim-go` automatically tries to be smart and sets the current packages import\npath as the `scope` for you. If the command needs a scope, you're mostly\ncovered. Most of the times this is enough, but for some queries you might to\nchange the scope setting. To make it easy to change the `scope` on the fly with\nhave a specific setting called `:GoGuruScope`\n\nIf you call it, it'll return an error: `guru scope is not set`. Let us change\nit explicitly to the `github.com/fatih/vim-go-tutorial\" scope: \n\n```\n:GoGuruScope github.com/fatih/vim-go-tutorial\n```\n\nYou should see the message:\n\n```\nguru scope changed to: github.com/fatih/vim-go-tutorial\n```\n\nIf you run `:GoGuruScope` without any arguments, it'll output the following\n\n```\ncurrent guru scope: github.com/fatih/vim-go-tutorial\n```\n\nTo select the whole `GOPATH` you can use the `...` argument:\n\n```\n:GoGuruScope ...\n```\n\nYou can also define multiple packages and also subdirectories. The following\nexample selects all packages under `github.com` and the `golang.org/x/tools`\npackage:\n\n```\n:GoGuruScope github.com/... golang.org/x/tools\n```\n\nYou can exclude packages by prepending the `-` (negative) sign to a package.\nThe following example selects all packages under `encoding` but not\n`encoding/xml`:\n\n```\n:GoGuruScope encoding/... -encoding/xml\n```\n\nTo clear the scope just pass an empty string:\n\n```\n:GoGuruScope \"\"\n```\n\nIf you're working on a project where you have to set the scope always to the\nsame value and you don't want to call `:GoGuruScope` everytime you start Vim,\nyou can also define a permanent scope by adding a setting to your `vimrc`. The\nvalue needs to be a list of string types. Here are some examples from the\ncommands above:\n\n```\nlet g:go_guru_scope = [\"github.com/fatih/vim-go-tutorial\"]\nlet g:go_guru_scope = [\"...\"]\nlet g:go_guru_scope = [\"github.com/...\", \"golang.org/x/tools\"]\nlet g:go_guru_scope = [\"encoding/...\", \"-encoding/xml\"]\n```\n\nFinally, `vim-go` tries to auto complete packages for you while using\n`:GoGuruScope` as well. So when you try to write\n`github.com/fatih/vim-go-tutorial` just type `gi` and hit `tab`, you'll see\nit'll expand to `github.com`\n\n---\n\nAnother setting that you should be aware are build tags  (also called build\nconstraints). For example the following is a build tag you put in your Go\nsource code:\n\n```\n// +build linux darwin\n```\n\nSometimes there might be custom tags in your source code, such as:\n\n```\n// +build mycustomtag\n```\n\nIn this case, guru will fail as the underlying `go/build` package will be not\nable to build the package. So all `guru` related commands will fail (even\n`:GoDef` when it uses `guru`). Fortunately `guru` has a `-tags` flag that\nallows us to pass custom tags. To make it easy for `vim-go` users we have a\n`:GoBuildTags`\n\nFor the example just call the following:\n\n```\n:GoBuildTags mycustomtag\n```\n\nThis will pass this tag to `guru` and from now on it'll work as expected. And\njust like `:GoGuruScope`, you can clear it with:\n\n```\n:GoBuildTags \"\"\n```\n\nAnd finally if you wish you can make it permanent with the following setting:\n\n```\nlet g:go_build_tags = \"mycustomtag\"\n```\n\n# Refactor it\n\n### Rename identifiers\n\nRenaming identifiers is one of the most common tasks. But it's also something\nthat needs to be done carefully in order not to break other packages as well. Also just\nusing a tool like `sed` is sometimes not useful, as you want AST aware\nrenaming, so it only should rename identifiers that are part of the AST (it\nshould not rename for example identifiers in other non Go files, say build\nscripts)\n\nThere is a tool that does renaming for you, which is called `gorename`.\n`vim-go` uses the `:GoRename` command to use `gorename` under the hood.  Let us\nchange `main.go` to the following content:\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype Server struct {\n\tname string\n}\n\nfunc main() {\n\ts := Server{name: \"Alper\"}\n\tfmt.Println(s.name) // print the server name\n}\n\nfunc name() string {\n\treturn \"Zeynep\"\n}\n```\n\nPut your cursor on top of the `name` field inside the `Server` struct and call\n`:GoRename bar`.  You'll see all `name` references are renamed to `bar`. The\nfinal content would look like:\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype Server struct {\n\tbar string\n}\n\nfunc main() {\n\ts := Server{bar: \"Alper\"}\n\tfmt.Println(s.bar) // print the server name\n}\n\nfunc name() string {\n\treturn \"Zeynep\"\n}\n```\n\nAs you see, only the necessary identifiers are renamed, but the function `name`\nor the string inside the comment is not renamed. What's even better is that\n`:GoRename` searches all packages under `GOPATH` and renames all identifiers\nthat depend on the identifier. It's a very powerful tool.\n\n### Extract function\n\nLet's move to another example. Change your `main.go` file to:\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tmsg := \"Greetings\\nfrom\\nTurkey\\n\"\n\n\tvar count int\n\tfor i := 0; i \u003c len(msg); i++ {\n\t\tif msg[i] == '\\n' {\n\t\t\tcount++\n\t\t}\n\t}\n\n\tfmt.Println(count)\n}\n```\n\nThis is a basic example that just counts the newlines in our `msg` variable. If\nyou run it, you'll see that it outputs `3`. \n\nAssume we want to reuse the newline counting logic somewhere else. Let us\nrefactor it. Guru can help us in these situations with the `freevars` mode. The\n`freevars` mode shows variables that are referenced but not defined within a\ngiven selection. \n\nLet us select the piece in `visual` mode:\n\n```go\nvar count int\nfor i := 0; i \u003c len(msg); i++ {\n\tif msg[i] == '\\n' {\n\t\tcount++\n\t}\n}\n```\n\nAfter selecting it, call `:GoFreevars`. It should be in form of\n`:'\u003c,'\u003eGoFreevars`. The result is again a quickfix list and it contains all the\nvariables that are free variables. In our case it's a single variable and the\nresult is:\n\n\n```go\nvar msg string\n```\n\nSo how useful is this? This little piece of information is enough to refactor\nit into a standalone function. Create a new function with the following content:\n\n```go\nfunc countLines(msg string) int {\n\tvar count int\n\tfor i := 0; i \u003c len(msg); i++ {\n\t\tif msg[i] == '\\n' {\n\t\t\tcount++\n\t\t}\n\t}\n\treturn count\n}\n```\n\nYou'll see that the content is our previously selected code. And the input to\nthe function is the result of `:GoFreevars`, the free variables. We only\ndecided what to return (if any). In our case we return the count. Our `main.go` will be in the form of:\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tmsg := \"Greetings\\nfrom\\nTurkey\\n\"\n\n\tcount := countLines(msg)\n\tfmt.Println(count)\n}\n\nfunc countLines(msg string) int {\n\tvar count int\n\tfor i := 0; i \u003c len(msg); i++ {\n\t\tif msg[i] == '\\n' {\n\t\t\tcount++\n\t\t}\n\t}\n\treturn count\n}\n```\n\nThat's how you refactor a piece of code. `:GoFreevars` can be used also to\nunderstand the complexity of a code. Just run it and see how many variables are\ndependent to it.\n\n# Generate it\n\nCode generation is a hot topic. Because of the great std libs such as go/ast,\ngo/parser, go/printer, etc.. Go has the advantage of being able to create great generators\neasily. \n\nFirst we have the `:GoGenerate` command that calls `go generate` under the\nhood. It just works like `:GoBuild`, `:GoTest`, etc.. If there are any errors it\nalso shows them so you can easily fix it.\n\n### Method stubs implementing an interface\n\nInterfaces are really great for composition. They make your code easier to deal\nwith. It's also easier for you to create tests as you can mock functions that\naccept an interface type with a type that implements methods for testing.\n\n\n`vim-go` has support for the tool [impl](https://github.com/josharian/impl).\n`impl` generates method stubs that implement a given interface. Let us change\n`main.go`'s content to the following:\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype T struct{}\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n```\n\nPut your cursor on top of `T` and type `:GoImpl`. You'll be prompted to write\nan interface. Type `io.ReadWriteCloser` and hit enter. You'll see the content\nchanged to:\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype T struct{}\n\nfunc (t *T) Read(p []byte) (n int, err error) {\n\tpanic(\"not implemented\")\n}\n\nfunc (t *T) Write(p []byte) (n int, err error) {\n\tpanic(\"not implemented\")\n}\n\nfunc (t *T) Close() error {\n\tpanic(\"not implemented\")\n}\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n```\n\nThat's really neat as you see. You can also just type `:GoImpl\nio.ReadWriteCloser` when you're on top of a type and it'll do the same.\n\nBut you don't need to put your cursor on top of a type.  You can invoke it from\neverywhere. For example execute this:\n\n```\n:GoImpl b *B fmt.Stringer\n```\n\nYou'll see the following will be created:\n\n```go\nfunc (b *B) String() string {\n\tpanic(\"not implemented\")\n}\n```\n\nAs you see this is very helpful, especially if you have a large interface with\nlarge method set. You can easily generate it, and because it uses `panic()`\nthis compiles without any problem. Just fill the necessary parts and you're\ndone.\n\n# Share it\n\n`vim-go` has also features to easily share your code with other via\nhttps://play.golang.org/. As you know the Go playground is a perfect place to\nshare small snippets, exercises and/or tips \u0026 tricks. There are times you are\nplaying with an idea and want to share with others. You copy the code and visit\nplay.golang.org and then paste it.  `vim-go` makes all these better with the\n`:GoPlay` command.\n\nFirst let us change our `main.go` file with the following simple code:\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"vim-go\")\n}\n```\n\nNow call `:GoPlay` and hit enter. You'll see that `vim-go` automatically\nuploaded your source code `:GoPlay` and also opened a browser tab that shows\nit. But there is more. The snippet link is automatically copied to your\nclipboard as well. Just paste the link to somewhere. You'll see the link is the\nsame as what's on play.golang.org.\n\n`:GoPlay` also accepts a range. You can select a piece of code and call\n`:GoPlay`. It'll only upload the selected part.\n\nThere are two settings to tweak the behavior of `:GoPlay`. If you don't like\nthat `vim-go` opens a browser tab for you, you can disable it with:\n\n```\nlet g:go_play_open_browser = 0\n```\n\nSecondly, if your browser is misdetected (we're using `open` or `xdg-open`) you\ncan manually set the browser via:\n\n```\nlet g:go_play_browser_command = \"chrome\"\n```\n\n# HTML template\n\nBy default syntax highlighting for Go HTML template is enabled for `.tmpl` files.\nIf you want to enable it for another filetype add the following setting to your `.vimrc`:\n\n```\nau BufRead,BufNewFile *.gohtml set filetype=gohtmltmpl\n```\n\n# Donation\n\nThis tutorial was created by me in my spare time. If you like it and would\nlike to donate, you now you can be a fully supporter by [being a\npatron](https://www.patreon.com/fatih)! \n\nBy being a patron, you are enabling vim-go to grow and mature, helping me to\ninvest in bug fixes, new documentation, and improving both current and future\nfeatures. It's completely optional and is just a direct way to support vim-go's\nongoing development. Thanks!\n\n[https://www.patreon.com/fatih](https://www.patreon.com/fatih)\n\n## TODO Commands\n* :GoPath\n* :AsmFmt\n\n","funding_links":["https://www.patreon.com/fatih)!","https://www.patreon.com/fatih"],"categories":["Vim Script"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffatih%2Fvim-go-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffatih%2Fvim-go-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffatih%2Fvim-go-tutorial/lists"}