Automatic code reloading in Go

 

I wrote a short Bash script to automatically reload Go programs.

The script acts as a light wrapper around go run, stopping and restarting it whenever a .go file in your current directory or $GOPATH/src folder is saved. I've been using it mainly when developing web applications, in the same way that I use Shotgun or Guard when working with Ruby.

You can grab this from the GitHub repository.

File: go-reload
#!/bin/bash
function monitor() {
  if [ "$2" = "true" ];  then
    # Watch all files in the specified directory
    # Call the restart function when they are saved
    inotifywait -q -m -r -e close_write -e moved_to $1 |
    while read line; do
      restart
    done
  else
    # Watch all *.go files in the specified directory
    # Call the restart function when they are saved
    inotifywait -q -m -r -e close_write -e moved_to --exclude '[^g][^o]$' $1 |
    while read line; do
      restart
    done
  fi
}

# Terminate and rerun the main Go program
function restart {
  if [ "$(pidof $PROCESS_NAME)" ]; then
    killall -q -w -9 $PROCESS_NAME
  fi
  echo ">> Reloading..."
  eval "go run $ARGS &"
}

# Make sure all background processes get terminated
function close {
  killall -q -w -9 inotifywait
  exit 0
}

trap close INT
echo "== Go-reload"

WATCH_ALL=false
while getopts ":a" opt; do
  case $opt in
    a)
      WATCH_ALL=true
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 0
      ;;
  esac
done

shift "$((OPTIND - 1))"

FILE_NAME=$(basename $1)
PROCESS_NAME=${FILE_NAME%%.*}

ARGS=$@

# Start the main Go program
echo ">> Watching directories, CTRL+C to stop"
eval "go run $ARGS &"

# Monitor all /src directories on the GOPATH
OIFS="$IFS"
IFS=':'
for path in $GOPATH
do
  monitor $path/src $WATCH_ALL &
done
IFS="$OIFS"

# If the current working directory isn't on the GOPATH, monitor it too
if [[ $PWD != "$GOPATH/"* ]]
then
  monitor $PWD $WATCH_ALL
fi

wait

Usage

The only dependency for this script is inotify-tools, which is used to monitor the filesystem for changes.

$ sudo apt-get install inotify-tools

Once you've downloaded (or copy-pasted) the script, you'll need to make it executable and move it to /usr/local/bin or another directory on your system path:

$ wget https://raw.github.com/alexedwards/go-reload/master/go-reload
$ chmod +x go-reload
$ sudo mv go-reload /usr/local/bin/

You should then be able to use the go-reload command in place of go run:

$ go-reload main.go
== Go-reload
>> Watching directories, CTRL+C to stop
If you enjoyed this post...

You might like to check out my other Go tutorials on this site, or if you're after something more structured, my books Let's Go and Let's Go Further cover how to build complete, production-ready web apps and APIS with Go.

Not sure how to structure your Go web application?
My new book guides you through the start-to-finish build of a real world web application in Go — covering topics like how to structure your code, manage dependencies, create dynamic database-driven pages, and how to authenticate and authorize users securely.