Is it possible to run Go code as a script?

see Neugram, Go scripting . From it's documentation:

#!/usr/bin/ng

// Start a web server to serve files.
import "net/http"
pwd := $$ echo $PWD $$
h := http.FileServer(http.Dir(pwd))
http.ListenAndServe(":8080", h)

As others noted, Go is a compiled language. Programs written in the Go language rely on the Go runtime which is added to the executable binary.

The Go runtime provides certain vital features such as garbage collection, goroutine scheduling, runtime reflection etc. Without them a Go app cannot work as guaranteed by the language spec.

A theoretical Go interpreter would have to simulate those features, which would essentially mean to include a Go runtime and a Go compiler. There is no such thing, and there is no need for that.
Also note that if the code is not yet compiled, that means the Go interpreter would have to contain all the standard library, because a Go "script" could legally refer to anything from the standard library (when a Go app is compiled, only things that it uses / refers to gets compiled into the executable binary).

To quickly test something, just use go run, which also compiles your app and builds an executable binary in a temporary folder, launches that temp file and cleans it when your app exits.

"Solutions" posted by others may "feel" like scripting, but they are nothing more than automating / hiding the process of compiling the Go source to an executable binary and then launching that binary. This is exactly what go run does (which also cleans up the temporary binary).


Absolutely possible on linux, props to cf: https://blog.cloudflare.com/using-go-as-a-scripting-language-in-linux

In case you don't want to use the already mentioned 'shebang' which may have limitations:

//usr/bin/env go run "$0" "$@"; exit "$?"

Do this instead:

# check if binfmt_misc is already active 
# (should already be done through systemd)
mount | grep binfmt_misc

# if not already mounted
sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc

# get gorun and place it so it will work
go get github.com/erning/gorun
sudo mv $GOPATH/bin/gorun /usr/local/bin

# make .go scripts being run with `gorun` wrapper script
echo ':golang:E::go::/usr/local/bin/gorun:OC' | sudo tee /proc/sys/fs/binfmt_misc/register

This is just for one-off testing. To make this persistant, I have this as the second last line in my /etc/rc.local's:

echo ':golang:E::go::/usr/local/bin/gorun:OC' | tee /proc/sys/fs/binfmt_misc/register 1>/dev/null

If you experience something like 'caching' issues during developing scripts, have a look at /tmp/gorun-$(hostname)-USERID.

I love bash, but as soon as you need a proper datastructures (bash arrays and associative arrays don't count due to unusability) you need another language. Golang is faster to write for me than is python, and any golang setup as depicted above will do for me. No battling python 2 vs 3, its libs and pip horrors, have a distributable binary at will, and just instantly be able to change the source for small one-off scripts is why this approach has definitely its upsides.


I am not an expert in go, but you can do something like this. I know this is not elegant, but may be something to start with :)

~$ cat vikas.go
//usr/bin/env go run "$0" "$@"; exit

package main

import "fmt"

func main() {
    fmt.Printf("Hello World\n")
}
~$

~$ ./vikas.go
Hello World
~$

Tags:

Go