32

I know AppEngine does this, but I'm not coding for it.

I tried using Guard from Ruby world, to listen on changes on .go files, and execute the following commands:

killall foo
go build -race
./foo &

But it never sends foo into background, it just hangs indefinitely.

How are you guys solving this problem? Solution has to be cross-platform too (GNU/Linux and Mac).

if __name__ is None
  • 11,083
  • 17
  • 55
  • 71

12 Answers12

34

Another option, if you have nodejs installed on your machine

install nodemon with -g npm i -g nodemon

go to your code dir and run:

nodemon --watch './**/*.go' --signal SIGTERM --exec 'go' run cmd/MyProgram/main.go

This will send SIGTERM every time any .go files changes and will run go run cmd/Myprogram/main.go

Fully cross platform.

Daniel Krom
  • 9,751
  • 3
  • 43
  • 44
  • 1
    However, installing `npm` *correctly* can be tricky (and platform-specific). `nvm` may be the best way to get `npm`: [npm throws error without sudo](https://stackoverflow.com/q/16151018/86967) – Brent Bradburn Jul 05 '20 at 03:24
  • 2
    NPM is fully cross platform, if you are using npm with sudo you just installed it wrongly. NVM doesn't solve cross platform it solves versioning – Daniel Krom Jul 05 '20 at 06:15
  • 1
    works like a charm as it does in the node world. – Krishnadas PC Jan 31 '21 at 13:16
  • 6
    In my case I had to specify the extension with -e: `nodemon -e go --signal SIGTERM --exec 'go' run .` – miqrc Sep 11 '21 at 09:59
  • Perfect. EXactly what I was looking for – ABDULLOKH MUKHAMMADJONOV Dec 16 '21 at 12:11
  • 3
    On Windows I had to use SIGKILL instead of SIGTERM – Giulio Nov 27 '22 at 18:01
  • in my case the command is not work successfully, I removed the `'` sign from the command, The end result of the command was as follows: `nodemon --watch ./**/*.go --signal SIGTERM --exec go run server.go`, my nodemon ver: **2.0.20**, my nodejs ver: **18.12.1** – abdooo9 Dec 04 '22 at 13:45
  • On Windows 10 (powershell) instead of using SIGTERM, I omitted the --signal option, nodemon would use the default kill signal, worked as expected. (While SIGTERM won't restart the process properly.) – Jake Zhang Dec 30 '22 at 15:54
  • This is just a modification to the above helpful comments. On windows, in your commandline (terminal), navigate to the root of your project(current directory) where you have your main.go file and run; nodemon --watch './**/*.go' --signal SIGKILL --exec go run main.go – alfrednoble Mar 09 '23 at 18:52
29

A friend wrote a simple Compile Daemon for go, worked like a charm for my own small net/http-projects.

You can find the repository here: https://github.com/githubnemo/CompileDaemon

krizz
  • 412
  • 3
  • 5
  • 1
    It looks like it doesn't run the binaries, it only builds them. Is there another solution to get us the rest of the way? – weberc2 Dec 21 '15 at 21:14
  • 2
    This is answer is old but CompileDaemon does run it too with `CompileDaemon -command="./MyProgram -my-options"` – Amir Raminfar Aug 31 '17 at 16:19
  • Compile Daemon is nice, but as I understand it can't run command without build. In some cases you just need to run "go run ./my_app" without build it first. In such cases, Compile Daemon is useless. – Igor Nikiforov Aug 24 '21 at 23:40
  • Can't install with go 1.18 / 1.19: https://github.com/githubnemo/CompileDaemon/issues/75 – bravmi Sep 19 '22 at 08:18
  • Here to replace CompileDaemon because I often get this error in PowerShell, Git Bash, CMD, etc: `watcher.Error:Windows system assumed buffer larger than it is, events have likely been missed.` – Shea Oct 15 '22 at 00:55
17

There is a go version of nodemon: https://github.com/mitranim/gow

go install github.com/mitranim/gow@latest

usage

# Start and restart on change
gow run .

# Pass args to the program
gow run . arg0 arg1 ...

# Run subdirectory
gow run ./subdir

# Vet and re-vet on change; verbose mode is recommended
gow -v vet

# Clear terminal on restart
gow -c run .

# Specify file extension to watch
gow -e=go,mod,html run .

# Help
gow -h
swyx
  • 2,378
  • 5
  • 24
  • 39
16

I've recently discovered a reflex tool. It's fast and works like a charm. It is very similar to nodemon (from nodejs world) and guard (from ruby world).

Most of the time I'm using it similar to below:

reflex -d none -s -R vendor. -r \.go$ -- go run cmd/server/main.go

But it maybe more convenient to have it's options in a file like .reflex, with contents like this:

-d none -s -R vendor. -r \.go$

So then you just run it like this

reflex $(cat .reflex) -- go run cmd/server/main.go

You can do same thing to "hot reload" tests:

reflex $(cat .reflex) -- go test ./... -v

There is also a config option where you can specify a number of commands you run same time, but I don't really use it.

evgeny.myasishchev
  • 4,141
  • 1
  • 20
  • 15
14

You can also try out Gin by Codegangsta. It's fire and forget.

https://github.com/codegangsta/gin

EDIT: I prefer CompileDaemon nowadays. Gin sometimes won't accept requests

13rac1
  • 1,057
  • 11
  • 14
Bijan
  • 25,559
  • 8
  • 79
  • 71
5

I used a tool called entr

To install brew install entr (mac)
or, sudo apt-get install entr (linux)

To recompile & run on .go file changes, run the following command ...

ls **/*.go | entr go run main.go
Ritwik
  • 1,597
  • 16
  • 17
  • 4
    the problem with this command is that it does not catch new files. It only watches files listed in the preliminary ls. –  Jul 11 '20 at 07:45
5

Best option is to install nodejs on your machine and use nodemon package

install nodemon with -g sudo npm install -g nodemon Also use sudo to avoid any write permission

Now go to your program dir and run:

nodemon --watch './**/*.go' --signal SIGTERM --exec 'go' run path-to-the-main-file-of-go-program-with-extension

This will send SIGTERM every time any .go files changes and will run go run main-go-file-of-program-with-extension

Fully cross platform. This will work for any programming language by just changing the command as

nodemon --watch './**/*.extension-of-programming-file-without-preceeding-dot' --signal SIGTERM --exec 'go' run path-to-the-main-file-of-program-with-extension
4

You can use nodemon for this. Simply create a nodemon.json file containing your configuration, files to watch, files to ignore, and command to execute when a file changes. Something like this configuration.

nodemon.json

{
  "watch": ["*"],
  "ext": "go graphql",
  "ignore": ["*gen*.go"],
  "exec": "go run scripts/gqlgen.go && (killall -9 server || true ) && go run ./server/server.go"
}

You do require nodejs for this to work.
But its far better then any other tool I've used so far that are go specific.

pandey909
  • 1,031
  • 8
  • 9
  • This is a lifesaver, thanks. Using nodemon is so much better than the standard appengine filewatcher. Here's the exec command that works for me for the interested "python dev_appserver.py app/ --automatic_restart=no" – hobberwickey Jun 04 '20 at 22:34
2

there are 2 main contenders here in GO world fresh & glide

But I will go with Fresh https://github.com/gravityblast/fresh

STEEL
  • 8,955
  • 9
  • 67
  • 89
2

After scrolling through the internet in search of a simple solution that was using standard linux tools (inotify & bash), I ended up creating this simple bash script that does the job.

I tested it in a container running golang:1.12 and using go run . to serve files. read the script before using it, as it kills the go run processes depending on a folder name, and if there are conflicts with other processes that you run it might kill them.

#!/bin/bash

go run . &
while inotifywait --exclude .swp -e modify -r . ;
do
    # find PID of the file generated by `go run .` to kill it. make sure the grep does not match other processes running on the system
    IDS=$(ps ax | grep "/tmp/go-build" | grep "b001/exe/main" | grep -v "grep" | awk '{print $1}')
    if [ ! -z "$IDS" ]
    then
        kill $IDS;
    fi
    go run . &
done;
hilnius
  • 2,165
  • 2
  • 19
  • 30
  • this works only if the program is modified in the current directory tree. If a package is located elsewhere in the fs is modified, this wont restart the app. smthg like this is smarter https://github.com/clementauger/grelot –  Jan 11 '20 at 22:44
  • 1
    I love the --exclude .swp... VI fun here. – David Valdivieso Aug 20 '20 at 22:53
1

While writing go in linux environment, you can watch the changed files and restart automatically without installing any additional programs in the local.

find . | grep '\.go' | entr -r go run .
mstgnz
  • 2,988
  • 1
  • 9
  • 13
-1

if anyone’s still looking for a solution, i wrote some shell scripts to do this and it’s usable via a docker environment, the repos at https://github.com/zephinzer/golang-dev

zephinzer
  • 1,077
  • 11
  • 9