Live Reload Go Projects with wgo

Live Reload Go Projects with wgo

Building web apps in Go is extremely rewarding. However, as Go’s a compiled language, to see changes, you need to restart the app. Needless to say that’s quite tedious! With live reloading, it doesn’t need to be.

Let’s put this in more context with a short example, which you can see below.

package main

import (

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("POST /", func(writer http.ResponseWriter, request *http.Request) {
		err := request.ParseForm()
		if err != nil {
			http.NotFound(writer, request)

		subject := request.PostForm.Get("subject")
		pattern := "^(?i:Ref(?i:erence)? ID: )(?P<refid>[0-9a-zA-Z]{14})$"
		subjectRegex := regexp.MustCompile(pattern)
		if !subjectRegex.MatchString(subject) {
			io.WriteString(writer, "Subject did not match the required format")
		log.Printf("%s matches pattern %s\n", subject, pattern)
		io.WriteString(writer, "Subject matched the required format")

	log.Print("Starting server on :4000")
	err := http.ListenAndServe(":4000", mux)

The code sets up a small web application that has one route which accepts POST requests. If the POST data contains an attribute named subject, whose value matches the regular expression in pattern, it will set the body of the response to: Subject matched the required format. Otherwise, the response’s body will be set to: Subject did not match the required format.

If you’re not that familiar with regular expressions, don’t worry. subject will match if it starts with either Reference: or Ref: and is followed by a 14 character string containing a combination of lower and uppercase letters, and digits between 0 and 9. For example: Ref ID: a4FGhd321ewqeU.

To test it out, you’d start the app running with go run main.go, and then send a curl request, such as the one below.

curl -X POST \
    -d subject="Ref ID: a4FGhd321ewqeU" \

You’d then see Subject matched the required format printed to the terminal.

However, if the regular expression or some other aspect of the code was refactored, you’d need to restart the app by pressing Ctrl + C and run go run main.go again.

As I said near the top of the post, that’s fine – at first. But, it rapidly becomes annoying when you’re doing it numerous times a day.

Live Reloading solves this problem

It does so by removing the need to manually stop and restart the app, because it automatically recompiles and restarts the code when it detects a change to a source file.

Live reloading is common in other languages, such as JavaScript with Webpack. There are a number of ways to do it in Go, but the simplest way that I’ve found is by using wgo (watcher-go).

To quote the project repository:

Too many file watchers either force you to wrap your commands into strings, require config files or log tons of noisy output to your stdout. In contrast, wgo is dead simple and silent by default. The implementation is also really short, most of it resides in just two files (wgo_cmd.go and main.go). You can read the entire codebase in one sitting, start here.

To use it is trivial, as all you need to do is use wgo where you would have used the standard Go binary in the past. For example:

wgo run main.go

Keep in mind that, depending on your $PATH configuration, you may have to provide the absolute path to wgo.

So, continuing with the previous example, let’s say that when subject matches the regular expression, you want to include its value in the response’s body. To do that, you’d change the call to io.WriteString() at the end of the route’s handler to the following:

io.WriteString(writer, fmt.Sprintf("Subject [%s] matched the required format", subject))

And, you’d include "fmt" in the import list. Then, when you save the changes, in the terminal tab or window where you ran wgo you’ll see output similar to the following, showing the app being recompiled and restarted.

2024/04/19 17:29:46 Starting server on :4000
2024/04/19 17:29:48 Starting server on :4000
2024/04/19 17:29:50 Starting server on :4000

Now, if you make the same curl request as before:

curl -X POST -d subject="Ref ID: a4FGhd321ewqeU" http://localhost:4000

You’ll see the following response:

Subject [Ref ID: a4FGhd321ewqeU] matched the required format

That’s how to use Live Reloading in Go

By using wgo (watcher-go) – for very little effort – you can save yourself a lot of time and effort restarting Go code to see the effects of the changes you make. It’s almost like you’re using a scripting language with all the benefits of a statically compiled one.

If you’ve not tried it already, I strongly recommend giving it a go at least to see what you think.

You might also be interested in these tutorials too...

Go mod tidy - A Quick Introduction
Fri, Apr 5, 2024

Go mod tidy - A Quick Introduction

What is go mod tidy and why you would use it? In this short tutorial you’ll get a brief introduction to what it is and see the essentials of how to use it.

Restrict HTTP Request Methods in Go 1.22
Thu, Apr 11, 2024

Restrict HTTP Request Methods in Go 1.22

Restricting HTTP request methods, when working with net/http prior to Go 1.22 was a little complicated. However, that’s all changed. Now, it’s pretty trivial. In this short tutorial, I’ll show you the new approach.

Debug Go Code with Visual Studio Code
Wed, Mar 27, 2024

Debug Go Code with Visual Studio Code

Recently, I started debugging Go code using Visual Studio Code. Some minor hiccups aside, it was pretty trivial to get up and going. This is the short version of what you need to do to get started.

Understanding Go's Empty Interface
Tue, Sep 12, 2023

Understanding Go's Empty Interface

Recently, while working with the Twilio Lookup API, I had the opportunity to properly learn about Go’s empty interface. During the process, I realised that I didn’t understand it properly, so took the opportunity to do so. Today, I am going to step through what it is and how simple they are to work with.

Want more tutorials like this?

If so, enter your email address in the field below and click subscribe.

You can unsubscribe at any time by clicking the link in the footer of the emails you'll receive. Here's my privacy policy, if you'd like to know more. I use Mailchimp to send emails. You can learn more about their privacy practices here.

Join the discussion

comments powered by Disqus