22

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
  • 10,423
  • 17
  • 53
  • 69

11 Answers11

28

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
  • 402
  • 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
20

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,233
  • 3
  • 38
  • 43
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,039
  • 9
  • 14
Bijan
  • 24,204
  • 7
  • 74
  • 69
14

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
  • 3,541
  • 1
  • 18
  • 14
5

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
  • 1,941
  • 5
  • 21
  • 35
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
  • 791
  • 6
  • 8
  • 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
3

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,409
  • 13
  • 14
  • 4
    the problem with this command is that it does not catch new files. It only watches files listed in the preliminary ls. – mh-cbon Jul 11 '20 at 07:45
2

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

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

STEEL
  • 7,168
  • 8
  • 62
  • 80
  • Why did you choose `fresh` over `glide`? What makes either of these more compelling to you than `CompileDaemon` or `reflex`? – ESV Jun 09 '20 at 20:29
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,137
  • 2
  • 17
  • 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 – mh-cbon Jan 11 '20 at 22:44
  • 1
    I love the --exclude .swp... VI fun here. – David Valdivieso Aug 20 '20 at 22:53
2

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
0

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
  • 969
  • 10
  • 9