if __name__ is None
if __name__ is None

Reputation: 11533

Go Auto-Recompile and Reload Server on file change

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

Upvotes: 49

Views: 67025

Answers (14)

mstgnz
mstgnz

Reputation: 3876

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" | entr -r go run .

or

find . -type f \( -name '*.go' -o -name '*.gohtml' \) | entr -r sh -c 'go build -o /tmp/build ./cmd && /tmp/build'

or with docker

find . -type f \( -name '*.go' -o -name '*.gohtml' \) | entr -r sh -c 'make && docker logs --follow $(APP_NAME)'

Upvotes: 7

aryomuzakki
aryomuzakki

Reputation: 106

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

Upvotes: 1

Akbarali
Akbarali

Reputation: 904

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

nodemon --exec go run index.go --signal SIGTERM

Upvotes: 1

ritik kumar srivastava
ritik kumar srivastava

Reputation: 552

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

Upvotes: 6

swyx
swyx

Reputation: 2511

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

Upvotes: 26

Ritwik
Ritwik

Reputation: 1725

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

Upvotes: 8

Daniel Krom
Daniel Krom

Reputation: 10060

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.

Upvotes: 52

hilnius
hilnius

Reputation: 2235

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;

Upvotes: 3

STEEL
STEEL

Reputation: 10007

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

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

Upvotes: 2

pandey909
pandey909

Reputation: 1189

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.

Upvotes: 4

zephinzer
zephinzer

Reputation: 1197

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

Upvotes: -1

Eugene Myasyshchev
Eugene Myasyshchev

Reputation: 4635

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.

Upvotes: 16

Bijan
Bijan

Reputation: 26469

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

Upvotes: 15

krizz
krizz

Reputation: 412

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

Upvotes: 29

Related Questions