As Go is becoming the language of the "system". I wonder if it's possible to run Go code as a script, without compiling it, is there any possibility to do that?
The motivation (as there were questions as for motivation), taken from How to use Scala as a scripting language
Problem You want to use Scala as a scripting language on Unix systems, replacing other scripts you’ve written in a Unix shell (Bourne Shell, Bash), Perl, PHP, Ruby, etc.
UPDATE:
I wonder how much I can "abuse" go run
to be able to have much Go code running as scripts
though compiled (which I like that its compiled) but it looks like go run
can give me the opportunity to replace scripting
, that is have source files on servers and run them as source while getting compiled by the go run
but I still manage sources and not executables.
UPDATE: in addition saw gorun
gorun - Script-like runner for Go source files.
Though there is a motivation and tools which tried to workaround not being able to run as script, I will not go for it, +I've been told it's not production ready and was advised not to use it in production because it's not production ready, it's out of it's purpose and would need dump the scripting convenience in favour of Go. (I don't have anything against compiling, static typing, I'm a big fan of it, but wanted something similar to scripting convenience).
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
~$
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With