Running your own local GoDoc server using systemd

The Go Programming Language has a lovely documentation system. All "exported" functions and types have Docstring type comments:

// Rectangle type represents the geometric shape known as a rectangle
type Rectangle struct {  
    Length float64
    Width  float64
}

The godoc tools understand these and can be used to navigate package documentation. Official Go documentation, such as that which is found at godoc.org, is generated using this simple system. However, this online doc repo is less helpful during local development.

Fear not, however - the godoc tool has your back here, too. While you can use the CLI tool to navigate package documentation, or of course simply read the source code, it can be more user-friendly to do so via a godoc.org-like web interface. It is also helpful to be able to see what your package documentation will look like once published.

To that end, this article illustrates how to setup a local godoc http server - complete with automatic reloading when .go files are saved!

Requirements

  • systemd
  • godoc tool
  • In this example, we're tying the service restart into the VSCode Editor
  • a web browser
  • a go package to test with

You don't necessarily have to use systemd, any tool which can run a persistent service and restart it will do.

Show me the Sorcery

First, we'll need to install the godoc tool. Under Fedora/RHEL, this is easy:
dnf install golang-godoc

Then, we'll create a systemd service which will run godoc --http in the background. The following is a simple Jinja2 template I lay down using Ansible (which also configures the rest of my workstation). Just substitute {{ godoc_port }}!

This gets laid down as /etc/systemd/system/godoc.service

[Unit]
Description=godoc HTTP Server  
After=network.target

[Service]
Type=simple  
ExecStart=/usr/bin/godoc -http :{{ godoc_port }}  
User=root  
Group=root

[Install]
WantedBy=multi-user.target  

Great, now the service can be enabled and run:

sudo systemctl enable godoc

sudo systemctl start godoc

# sudo systemctl status godoc
● godoc.service - godoc HTTP Server
   Loaded: loaded (/etc/systemd/system/godoc.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2018-07-31 00:42:58 EDT; 36min ago
 Main PID: 3471 (godoc)
    Tasks: 13 (limit: 4915)
   Memory: 14.9M
   CGroup: /system.slice/godoc.service
           └─3471 /usr/bin/godoc -http :8995

Jul 31 00:42:58 ilos systemd[1]: Stopped godoc HTTP Server.  
Jul 31 00:42:58 ilos systemd[1]: Started godoc HTTP Server.  

Imgur

I find it helpful to bookmark my own pkg/github.com/crielly/ path: ie http://localhost:8995/pkg/github.com/crielly/. Now, I can browse the godoc-generated pages for the code I'm working on locally:
Imgur

But my code changes and manually restarting that service sucks

Yep. So, I originally went down the path of trying to have Systemd watch my whole $GOPATH for changes and restart any time one happened. Turns out, you can monitor a file or a directory using Systemd, but you can't watch a whole bunch of unknown subdirectories. Therefore, I opted for something simpler - I used a Visual Studio Code extension called RunOnSave

To my vscode config, I simply added:

"emeraldwalk.runonsave": {
        "commands": [
            {
                "match": "\\.go$",
                "cmd": "sudo systemctl restart godoc"
            },
        ]
    }

And, of course, you'll need the extension installed.

But now I get a sudo prompt whenever I save a .go file!

No problem. We just need to add a very limited entry to /etc/sudoers.d/godoc:

crielly ALL=NOPASSWD:/usr/bin/systemctl restart godoc  

Now you can run that specific command using sudo without being prompted for a password. Any time vscode saves a .go file, the service will be restarted and you'll always have a nice fresh local godoc server.