Gopls
Gopls
Intro
Mid of 2018, I decided to switch from Java to Go. Language change leads to change editor and whole ecosystem and workflow such as doing my job primarily from the terminal.
At the very beginning of my Go journey, I tried Vim as an editor(with vim-go), but I gave up because of a double burden such as learning a new language and a new editor at the same time. I switched back to a product well-known in the Java world company - JetBrains - which makes tools for software developers. Their IDE, GoLand provides effortless immersion in the Go world.
After I got familiar with Go itself I decided to give Vim another try. I still have been using it as my primary editor. From time to time I have to work with other languages(Javascript/NodeJS) and the question of how can I customize vim to work with any language arises.
I had a problem with Vim and Go as well. Vim-go itself is an umbrella for a set of Go tools. Part of them are provided by Go directly, others were written by enthusiast. With transition to the Go Modules some of them guru stopped working.
It was my gateway to gopls and Language Server Protocol.
In this post I try to answer the next questions:
- What is gopls?
- What problems does it solve?
- How does it work?
- What features does it have?
- Does it work well?
What is Gopls
gopls
(pronounced “Go please”) is the official Go language server developed by the Go team. It provides IDE features to any LSP -compatible editor.
You should not need to interact with gopls directly - it will be automatically integrated into your editor. The specific features and settings vary slightly by editor, so we recommend that you proceed to the documentation for your editor below.
From gopls design documentation:
- gopls should become the default editor backend for the major editors used by Go programmers, fully supported by the Go team.
- gopls will be a full implementation of LSP, as described in the LSP specification , to standardize as many of its features as possible.
- gopls will be clean and extensible so that it can encompass additional features in the future, allowing Go tooling to become best in class once more.
- gopls will support alternate build systems and file layouts, allowing Go development to be simpler and more powerful in any environment.
What problems does it solve
While Go has a number of excellent and useful command-line tools that enhance the developer experience, it has become clear that integrating these tools with IDEs can pose challenges. Support of these tools has relied on the goodwill of community members, and they have been put under a large burden of support at times as the language, toolchain and environments change. As a result many tools have ceased to work, have had support problems, or become confusing with forks and replacements, or provided an experience that is not as good as it could be.
This is fine for tools used occasionally, but for core IDE features, this is not acceptable. Autocompletion, jump to definition, formatting, and other such features should always work, as they are key for Go development. The Go team will create an editor backend that works in any build system. It will also be able to improve upon the latency of Go tools, since each tool will no longer have to individually run the type-checker on each invocation, instead there will be a long-running process and data can be shared between the definitions, completions, diagnostics, and other features.
How does it work and what features does it have
Implementation
View/Session/Cache Throughout the code there are references to these three concepts, and they build on each other. At the base is the Cache. This is the level at which we hold information that is global in nature, for instance information about the file system and its contents.
Above that is the Session, which holds information for a connection to an editor. This layer hold things like the edited files (referred to as overlays).
The top layer is called the View. This holds the configuration, and the mapping to configured packages.
The purpose of this layering is to allow a single editor session to have multiple views active whilst still sharing as much information as possible for efficiency. In theory if only the View layer existed, the results would be identical, but slower and using more memory.
It is well illustrated in tools/session.go
|
|
Debug gopls
To get more information on how gopls
works we need to make proper settings.
For Neovim(neovim/nvim-lspconfig plugin) in init.vim
:
|
|
For VS Code in Go plugin settings in setting.json
|
|
Check log in /tmp/gopls.log
and /tmp/vs-gopls.log
respectively
Open editor with Go project
When we open editor with open Go project next job should be done:
- starting server
- initialization
- open session and make session handshake
- works in progress: setting up workspace folder base on (go.mod/go.sum), loading packages (progress notifications send to an editor
From
|
|
We see:
worksapce folders and root path:
|
|
clientInfo:
|
|
and
|
|
The we see group of capabilities:
|
|
We take a look closet at textDocument/definition
, textDocument/hover
, textDocument/codeActions
and textDocument/completion
Open document, definition, completion, hover and code actions
To understand how gopls
works we need to take a look at LSP.
From the LSP Overview:
a language server runs as a separate process and development tools communicate with the server using the language protocol over JSON-RPC. Below is an example for how a tool and a language server communicate during a routine editing session:
To play around I use my simple Go project
|
|
Neovim
VSCode
I go to string 16 (in request it is line 15, probably numeration starts with 0) and put cursor to the sumbol p
of func plus
and invoke go to definition
:
|
|
Go to the line 21 and put cursor after fmt.
and invoke autocompletion:
Neovim
VSCode
|
|
Undo autocompletion, put cursor to the P
, beginning of Prinltn
and invoke hover:
Neovim:
VSCode:
|
|
This example illustrates how the protocol communicates with the language server at the level of document references (URIs) and document positions. These data types are programming language neutral and apply to all programming languages. The data types are not at the level of a programming language domain model which would usually provide abstract syntax trees and compiler symbols (for example, resolved types, namespaces, …). The fact, that the data types are simple and programming language neutral simplifies the protocol significantly. It is much simpler to standardize a text document URI or a cursor position compared with standardizing an abstract syntax tree and compiler symbols across different programming languages.
Go to next line and add code:
|
|
Diagnostic says us:
|
|
If we invoke code actions
, in Neovim we see
in VSCode:
and in gopls logs:
|
|
Does it work well
Gopls is a default editor Go backend for the most popular editors. To get started with gopls, install an LSP plugin in your editor of choice.
Conclusion
Gopls allows you get best Go developing experience in an editor of you choice. Full support by the Go team means it is free, stable and reliable tool.