Go Auto-Recompile and Reload Server on file change
Asked Answered
S

14

42

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).

Signatory answered 26/10, 2013 at 9:31 Comment(1)
Not really a "Go" question, have you tried: nohup ./foo > /var/log/foo/out.log &Excretion
C
39

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.

Cladding answered 18/6, 2020 at 14:54 Comment(9)
However, installing npm correctly can be tricky (and platform-specific). nvm may be the best way to get npm: npm throws error without sudoShote
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 versioningCladding
works like a charm as it does in the node world.Cephalic
In my case I had to specify the extension with -e: nodemon -e go --signal SIGTERM --exec 'go' run .Scheld
Perfect. EXactly what I was looking forTarahtaran
On Windows I had to use SIGKILL instead of SIGTERMWasteful
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.1Bobo
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.)Lauralauraceous
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.goJoinery
T
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

Twitch answered 13/11, 2013 at 10:58 Comment(5)
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?Retorsion
This is answer is old but CompileDaemon does run it too with CompileDaemon -command="./MyProgram -my-options"Gainly
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.Tapster
Can't install with go 1.18 / 1.19: github.com/githubnemo/CompileDaemon/issues/75Gam
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.Refutation
M
22

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
Mainsail answered 29/7, 2021 at 21:56 Comment(3)
Only works for Linux?Refutation
It works like a charm; I tested it on Mac. Thanks for sharing.Embellish
doesn't work on windowsYttrium
R
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.

Roil answered 18/6, 2018 at 21:13 Comment(4)
It looks like reflex (now) has a way to read a configuration file directly. Your third example could be rewritten as reflex -c .reflex -- go run cmd/server/main.go.Lh
thanks @ESV, didn't notice that change, good to know that.Roil
And it's Linux only. :(Tapster
well, it works on OSX as well, never tried Windows though.Roil
C
15

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

Cocke answered 20/2, 2015 at 12:40 Comment(0)
M
8

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
Mistassini answered 10/7, 2020 at 13:38 Comment(2)
the problem with this command is that it does not catch new files. It only watches files listed in the preliminary ls.Vulcanite
ls -d **/*.go | entr -d go run main.go this works for new files too...more at eradman.com/entrprojectLadylove
R
6

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
Rob answered 31/8, 2021 at 9:56 Comment(0)
F
5

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

find . -name "*.go" | grep '\.go' | entr -r go run .

or

find . -name "*.go" | entr -r go run .
Follicle answered 18/1, 2023 at 16:53 Comment(3)
This worked for me. You can also drop grep by using find . -name "*.go" instead.Pepito
I prefer this solution over nodemon because nodemon is throwing an error of file watch limit reached. I know we can increase the limit but for me it requires sudo access which I don't have.Ovotestis
elegant solution that deserves to be at the topTopeka
E
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.

Eyesore answered 14/2, 2019 at 5:19 Comment(1)
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"Discoid
V
3

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;
Vitiligo answered 10/1, 2020 at 23:56 Comment(2)
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 github.com/clementauger/grelotVulcanite
I love the --exclude .swp... VI fun here.Peppie
D
2

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

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

Dabber answered 18/9, 2019 at 18:58 Comment(2)
Why did you choose fresh over glide? What makes either of these more compelling to you than CompileDaemon or reflex?Lh
fresh is unmaintained now 😔Jews
C
1

This method worked for me, maybe it will work for you too.

nodemon --exec go run index.go --signal SIGTERM
Cobden answered 28/12, 2023 at 6:51 Comment(0)
L
1

I tried to use Fresh and Realize but some error happened.

So I use Air and works great so far

Summarized Steps:

  1. Install with go install (for go v1.22 or higher)

    go install github.com/cosmtrek/air
    
  2. go to project directory and initialize .air.toml default config file

    air init
    
  3. run air

    air
    

More explanation available on Air github repository

Lissome answered 24/3 at 10:15 Comment(0)
D
-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

Deadpan answered 20/12, 2018 at 16:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.