Gopls: Language server protocol implementation for Go

语言: CN / TW / HK

gopls (pronounced: "go please") is an implementation of the Language Server Protocol (LSP) server for Go. The LSP allows any text editor to be extended with IDE-like features (see for details).


gopls is currently under active development by the Go team. The code is in the x/tools repository, in and . Because we are actively working on gopls , it is not stable. If you choose to use it, be aware that things may regularly break or change.


First, install gopls by running go get -u . We suggest using VSCode with the Go plugin.

Turning off both build and vet on save is useful to avoid duplicating diagnostics from both gopls and VSCode-Go. gopls also replicates the functionality of both gofmt and goimports .

Editors instructions

  • VSCode, through the VSCode-Go plugin, with the following configuration:
"go.useLanguageServer": true,
"go.languageServerExperimentalFeatures": {
        "diagnostics": true // for diagnostics as you type
"[go]": {
    "editor.snippetSuggestions": "none",
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
        "source.organizeImports": true
"gopls": {
    "usePlaceholders": true, // add parameter placeholders when completing a function
    "enhancedHover": true,   // experimental to improve quality of hover (will be on by default soon)

VSCode will complain about the "gopls" settings, but they will still work. Once we have a consistent set of settings, we will make the changes in the VSCode plugin necessary to remove the errors.

  • Vim, through vim-go , with the following configuration:
let g:go_def_mode='gopls'
" Launch gopls when Go files are in use
let g:LanguageClient_serverCommands = {
       \ 'go': ['gopls']
       \ }
" Run gofmt and goimports on save
autocmd BufWritePre *.go :call LanguageClient#textDocument_formatting_sync()
  • Vim/Neovim, through vim-lsp , with the following configuration:
augroup LspGo
  autocmd User lsp_setup call lsp#register_server({
      \ 'name': 'go-lang',
      \ 'cmd': {server_info->['gopls']},
      \ 'whitelist': ['go'],
      \ })
  autocmd FileType go setlocal omnifunc=lsp#complete
  "autocmd FileType go nmap <buffer> gd <plug>(lsp-definition)
  "autocmd FileType go nmap <buffer> ,n <plug>(lsp-next-error)
  "autocmd FileType go nmap <buffer> ,p <plug>(lsp-previous-error)
augroup END
  • Vim, through ale :
let g:ale_go_langserver_executable = 'gopls'

see this issue

  • Emacs, through lsp-mode . gopls is built in now as a client, so no special config is necessary. Here is an example (assuming you are using use-package ) to get you started:
(use-package lsp-mode
  :commands lsp)

(add-hook 'go-mode-hook #'lsp)

;; optional - provides fancier overlays
(use-package lsp-ui
  :commands lsp-ui-mode)

;; if you use company-mode for completion (otherwise, complete-at-point works out of the box):
(use-package company-lsp
  :commands company-lsp)


Contributions are welcome, but since development is so active, we request that you file an issue and claim it before starting to work on something. Otherwise, it is likely that we might already be working on a fix for your issue.

Please see all available issues under the gopls label on the Go issue tracker. Any issue without an assignee and with the label "Suggested" is fair game - just assign yourself or comment on the issue before you begin working!


  • Why is it called gopls ? Since gopls works both as a language server and as a command line tool, we wanted a name that could be used as a verb. For example, gopls check should read as "go please check." See: .

Integrator FAQ

What follows is a list of questions/ideas/suggestions for folks looking to integrate gopls within an editor/similar.

A good starting point for any integrator is the Language Service Protocol Specification . represents a Go definition of the spec.

What does gopls support?

The most accurate answer to this question is to examine the InitializeResult response to Initialize , specifically the capabilities field of type ServerCapabilities

UTF-8, UTF-16 and position information

As an example, the Hover method takes TextDocumentPositionParams which has a position field of type Position . The key point to note from that last link is the following:

A position inside a document (see Position definition below) is expressed as a zero-based line and character offset. The offsets are based on a UTF-16 string representation. So a string of the form a?b the character offset of the character a is 0, the character offset of ? is 1 and the character offset of b is 3 since ? is represented using two code units in UTF-16.

i.e. integrators will need to calculate UTF-16 based column offsets. For Go-based integrators, the will be of use. #31080 tracks making span and other useful packages non-internal.

textDocument/formatting response

At the time of writing (2019-03-28) the []TextEdit response to textDocument/formatting comprises range-based deltas. The spec is not explicit about how these deltas should be applied, instead simply stating:

If multiple inserts have the same position, the order in the array defines the order in which the inserted strings appear in the resulting text.

i.e. it specifies only the resulting state of the document.

Applying the array of deltas received in reverse order achieves the desired result that holds with the spec.

RPC response errors and related discussions are looking to help shape what it means for a server method to return an error. i.e.


This answer is therefore a WIP.

Files that change "outside the editor"

For example, files that are created/modified/removed as a result of go generate . Per @ianthehat :

The plan is to have the client do all the work for us. Specifically we are going to start using workspace/didChangeWatchedFiles to monitor all the files we are caching AST's for

This is currently not implemented (2019-04-15).

Additional Information

Questions can be directed toward @stamblerre or @ianthehat . For consistent updates on the development progress of gopls, see the notes from the golang-tools meetings ( ).