Including patching the Linux kernel itself?
Rémy.
With binfmt_misc support this isn't necessary. You can get Linux to recognize
the go script and run it based on the extension or magic number. To get it to
run via the extension you can do this on any Debian based system.
apt-get install binfmt-support
cd ~
cat > gorun << EOF
#!/bin/sh
cd \$(dirname \$@)
/full/path/to/go run "\$(basename \$@)"
EOF
chmod 755 gorun
sudo update-binfmts --install go ~/gorun --extension go
It is probably possible to get this working with the magic number using as
well. This could be added to the packages for those platforms. But this is
Linux specific.
--
John Eikenberry
[ j...@zhar.net - http://zhar.net ]
[ PGP public key @ http://zhar.net/jae_at_zhar_net.gpg ]
________________________________________________________________________
"Perfection is attained, not when no more can be added, but when no more
can be removed." -- Antoine de Saint-Exupery
I created a go program to register .go files with binfmt and then run
them with go run.
Install go-binfmt.
$ go get github.com/str1ngs/go-binfmt
To use go-binfmt first register it with binfmt.
$ sudo $GOPATH/bin/go-binfmt -register
To run a go file give it executable permissions, and then run it.
$ chmod +x main.go
$ ./main.go
If you know about gorun and goscript, then why do you ask?
On Mon, Feb 27, 2012 at 11:59, Miki Tebeka <miki....@gmail.com> wrote:
> I'm using "gorun" now, but I was wondering if this can be done in "pure" go
> toolchain.
I've already offered to include gorun into the standard distribution,
but the consensus was that having it as its own tool was a better
approach.
This sounds fine, to be honest. "go get launchpad.net/gorun" isn't
really a big deal.
--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/plus
http://niemeyer.net/twitter
http://niemeyer.net/blog
-- I'm not absolutely sure of anything.
> I prefer native "#!" support of Go. (Just like python).
Go is not just like Python. It's abusive to run a compiler and linker every time a command is run.
The design of Go is careful about dependencies and the cost of program construction. That care should not be disregarded.
You are not expected to understand this.
-rob
That's only because Windows isn't home for Gustavo. Patches that
enable it to work without changing Linux/MacOS semantics accepted,
though.
I think this is what Rob pointed above.
> The idea would need a compiler cache in order to work.
gorun does that.
--
André Moraes
http://andredevchannel.blogspot.com/
> The Go compiler is slow for this. It would be disturbing to wait up toI think this is what Rob pointed above.
> 1 second every time you run the script.
If implemented, it wouldn't change the existing properties of Go
compiler for existing use cases.
Even if it was slow, that's a new use case and if I'm willing to take
the startup hit for the convenience of being able to replace my Python
scripts with scripts written in Go then why someone else's opinion of
what is slow should matter?
Except it doesn't have to be slow. Correct me if I'm wrong, but go
compiler is already smart enough to not recompile and relink if the
source code being compiled and all of it's dependencies hasn't changed
and that's exactly the logic needed for making this use case fast.
Really all we're asking is that Go doesn't barf with syntax error if
first line of the .go file starts with #! and skip it.
Even if Go team doesn't personally think that gorun-like usage is
useful or needs to be supported by go distribution, that small change
alone would allow others to easily implement gorun-like capability.
It would be preferable to have that simply as part of Go distribution
but the second best option would be apt-get install gorunner written
by whomever and being able to chmod u+x myscript.go && ./myscript.go
to run it as long as it has the magic #!
-- kjk
You dropped the last sentence of my message.
-rob
The standard Go distribution shouldn't encourage developers to write
slow code. Adding a #! syntax would be an encouragement to do
something silly. Right now the silliness is limited to the people
determined enough to install an external program and thus requires
that they at least have thought about how silly it is.
Perhaps a better option for you is to setup an inotify that runs the
compiler every time you change one of the scripts, thus it only needs
to invoke the compiler when changes occur instead of every time the
script is run. That would be far more sensible.
--
=====================
http://jessta.id.au
If you want to stay on topic and backup your previous assertions that
gorun-like tool cannot be made fast or englighten us why it's such a
big deal to skip #! then please do, preferably in non-cryptic way.
-- kjk
I described how it's trivial to avoid speed penalty in that system so
your performance arguments are wrong.
Sure, there are many possible Goldberg contraptions that I could use
but that defeats the purpose which is: convenience.
There's a reason #! convention is honored by virtually every dynamic
language implementation:
"silly" people want it because people use it because it's a useful feature.
-- kjk
The issue has been discussed ad nauseam on this very mailing list.
Search the archives. (I apologize that the Groups search isn't very
good.)
This was a design decision and such decisions can't suit everyone. We
can talk about it all day, but the decision has already been made. For
what it's worth, no new points have been raised by this thread.
Jessta has done a reasonable job of summarizing the rationale.
On 29 February 2012 11:57, Krzysztof Kowalczyk <kkowa...@gmail.com> wrote:
> There's a reason #! convention is honored by virtually every dynamic
> language implementation:
> "silly" people want it because people use it because it's a useful feature.
Go isn't a dynamic language.
You seem hurt that your opinion isn't being heard - but please know
that you are not alone in your opinions. Others have held the same
opinion and have already been heard. Don't take it personally that we
don't have time to re-hash old discussions. It's not much fun, anyway.
Andrew
Why are you spending your energy arguing? Installing gorun is
trivial, and it works as you want. Just put it to good use and spend
your energy having fun with some Go code.
I don't care one way or the other about this feature but the FUD is ridiculous.
Serious misnomer...there's not much scripting happening when all the
sha-bang is being used for is to start the compiler, and in no way
does that require the source in the file to be dynamic. The compiler
runs the way it always does, as does the executable.
The Tiny C Compiler handles files being run from the system
(http://bellard.org/tcc/), which is what the shell is doing when it
sees a sha-bang on the first line of a file, just fine. But then that
makes perfect sense because all that's being scripted is the
invocation of the compiler.
E.g. when bash sees the sha-bang in a tcc file all it does is invoke
tcc with the -run option (from the sha-bang line) and the name of the
file to be compiled. When tcc sees the -run option it knows A) to skip
the first line of the file and B) compile the file then immediately
run the executable. That's it. WTF is the big deal.
#!/usr/local/bin/tcc -run
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
-joe
I understand the points of the opposition here but having things such as this and for example a repl is not at all a bad choice for a typed compiled language. Haskell has both and its statically super-typed.
I get by with gorun, it works fine and its not a hassle to have to install an extra bit of code. It does not make me not miss a repl however but it can be added later so it has never been a real worry though.
Can we visit this issue at some time later when Go 1 has landed and had more exposure?
I'm going to have to agree, that shebang support for a statically
compiled language is a unique feature. We understand that there is
some overhead with this, however it really does compliment Go
compilation speeds. (Also I could port all my pythong/ruby/bash crap
to a nice expressive language like go)
Also one point I would like to make it that with the release of Go1,
Having shebang support would actually help the Go bootstrap process,
Since we could rely on Go1 instead of say bash, We could say move
make.bash, all.bash to make.go all.go. Also we could possibly port a
bit of the C code in dist to go. And rely more on Go1 for
bootstrapping.
Just a thought.
I'm going to have to agree, that shebang support for a statically
compiled language is a unique feature. We understand that there is
some overhead with this, however it really does compliment Go
compilation speeds. (Also I could port all my pythong/ruby/bash crap
to a nice expressive language like go)
Also one point I would like to make it that with the release of Go1,
Having shebang support would actually help the Go bootstrap process,
Since we could rely on Go1 instead of say bash, We could say move
make.bash, all.bash to make.go all.go. Also we could possibly port a
bit of the C code in dist to go. And rely more on Go1 for
bootstrapping.
go run main.go works right now, on the same code that I use go build
on. Invoking go run from a shebang vs go run or go build, will have no
impact on how the code is written. And I can still import packages
which I would argue makes for less code in the long run, since I'll
use all my helper packages which all have test units.
>> Also one point I would like to make it that with the release of Go1,
>> Having shebang support would actually help the Go bootstrap process,
>> Since we could rely on Go1 instead of say bash, We could say move
>> make.bash, all.bash to make.go all.go. Also we could possibly port a
>> bit of the C code in dist to go. And rely more on Go1 for
>> bootstrapping.
> Chicken and egg. You have to start somewhere. Bash exists and works well.
Yes on unix, however tell that to the windows guys where we have
all.bat and make.bat.
I still don't see how that would help much with bootstrapping. Are you saying we should rewrite everything in Go and ship Go compiler binaries for all platforms we want to support? Sounds like a lot of work for a very marginal gain, and is hardly a good argument for shebang support since it comes down only to the difference between "./make.go" and "go run make.go", and that's a command you only type once.
Andrew
Right. The shebang is a magic number (no different from a binary
executable's magic number) and having it in a file doesn't
automatically make the file a script. If there's a callable program at
the end of the shebang string, options are collected, arg[0] is set to
the file name, and execv is called (shell_execve (execname, args,
env).
So adding "#!/usr/local/go/bin/go run" to a file and running it from
the command line is exactly the same as doing $ go run x.go
edit: args[0] = execname and not the file name
Good point, also porting to other Os/Arch would be an issue. So yes
bad example. might still be nice for windows though vs make.bat
> And is hardly a good argument for shebang support since it
> comes down only to the difference between "./make.go" and "go run make.go",
> and that's a command you only type once.
Yes, but that still has to be done every time, sure this is one case
where you can argue thats easy to type. The fact that go run exists
means that the Go team has situations where they find this useful,
adding shebang support to the compiler to avoid shell wrapper scripts
for those situations IMO is well worth the effort.
> I still don't see how that would help much with bootstrapping. Are youGood point, also porting to other Os/Arch would be an issue. So yes
> saying we should rewrite everything in Go and ship Go compiler binaries for
> all platforms we want to support? Sounds like a lot of work for a very
> marginal gain
bad example. might still be nice for windows though vs make.bat
> And is hardly a good argument for shebang support since itYes, but that still has to be done every time, sure this is one case
> comes down only to the difference between "./make.go" and "go run make.go",
> and that's a command you only type once.
where you can argue thats easy to type. The fact that go run exists
means that the Go team has situations where they find this useful,
adding shebang support to the compiler to avoid shell wrapper scripts
for those situations IMO is well worth the effort.
On Wed, Feb 29, 2012 at 4:59 PM, Mike Rosset <mike....@gmail.com> wrote:> I still don't see how that would help much with bootstrapping. Are youGood point, also porting to other Os/Arch would be an issue. So yes
> saying we should rewrite everything in Go and ship Go compiler binaries for
> all platforms we want to support? Sounds like a lot of work for a very
> marginal gain
bad example. might still be nice for windows though vs make.batWhy make.bat is bad?I don't think we should require a go compiler to be able to bootstrap.It will also make porting to other platforms difficult.
-rob
Yes, and some Linux/ARM systems do not even have bash, ie andriod. I
do think decoupling bootstrapping with bash, vs building from hg
without bash and Go1 would make build on windows alot easier even if
required you to install Go1 binaries. But all that is offtopic and
just a use case.
My real point is that I much rather be coding things in Go where
possible vs bash,bat,ruby,python and have the convenience of a
shebang. But all in all I can use go run, or a shell wrapper to go
run, in those cases so I wont press the issue.
> Also note, on some OS-Arch combinations (Linux/ARM), we simply can't provideYes, and some Linux/ARM systems do not even have bash, ie andriod. I
> a universal
> compiler binary which can be run on every possible platforms.
> soft/hard floating point, arm/thumb, oabi/eabi, different dynamic linker,
> different libc, etc.
do think decoupling bootstrapping with bash, vs building from hg
without bash and Go1 would make build on windows alot easier even if
Candy Mountain Charlie... http://www.youtube.com/watch?v=JPONTneuaF4
cmd.exe exists and works well.
What exactly are you trying to say?
--
Aram Hăvărneanu
> To try to explain I like the idea to builtin shebang in Go (maybe after
> Go1).
Why not just use https://wiki.ubuntu.com/gorun ?
This is an area where people can easily provide their own tools, and
where there is no obviously correct approach.
Ian
Or the quick and dirty (and ugly) method:
#!/usr/bin/env bash
tail -n +4 "in.go" > "out.go" && go run "out.go"
exit 0
package main
import (
"fmt"
)
func main( ) {
fmt.Println("Span And Eggs")
}
Yes, the three lines starting with the shebang go at the top of the
"go" source file, then
$ chmod +x ./in.go
$ ./in.go
gives:
prog.go:1: syntax error: unexpected #
prog.go:1: package statement must be first
prog.go:1: syntax error: unexpected /
If Go compiler simply skips #! line then yes, we can build tools that
work just as well as python or ruby #! scripts.
Since it doesn't, a given file .go file is either correct for the
compiler or correct for gorun but not for both which is not the same
level of convenience as in python or tinycc.
-- kjk
On Wed, Feb 29, 2012 at 6:46 AM, Ian Lance Taylor <ia...@google.com> wrote:
Because: http://golang.org/#%23!%2Fusr%2Fbin%2Fgorun%0A%0Apackage%20main%0A%0Afunc%20main()%20%7B%0A%20%20%20%20println(%22Hello%20world!%22)%0A%7D%0A> dlin <dli...@gmail.com> writes:
>
>> To try to explain I like the idea to builtin shebang in Go (maybe after
>> Go1).
>
> Why not just use https://wiki.ubuntu.com/gorun ?
>
> This is an area where people can easily provide their own tools, and
> where there is no obviously correct approach.
gives:
prog.go:1: syntax error: unexpected #
prog.go:1: package statement must be first
prog.go:1: syntax error: unexpected /
On Thu, 1 Mar 2012 08:34:58 -0800, Paul Borman <bor...@google.com> wrote:
> So if I understand you requirement, you require that the exact same file,
> which is a single file go program, be both compilable source as well as an
> executable script, is that more or less what you are saying?
>
> I hear the others saying you can easily make an executable script by
> prepending a go program with 3 lines of non-go code.
>
> A main argument I hear against the whole concept is that invoking the
> compiler for each and every call of the script is perhaps not the best use
> of cpu cycles when it is so easy to simply install the compiled version.
> Using gorun could mitigate this, but I am not sure that is true if you
> recreate the real go source each time. Both approaches seem flawed to me
> as they require someplace to build and run the program from.
>
> I feel like what you really would like is a go interpreter. Given the
> design of the Go language an interpreted go would either a) need to be a
> variant/subset of the language or b) the interpreter will need to compile
> the code internally anyhow as the first statement may very well depend on
> the final statement of the source.
there is a beginning of an interpreter over here:
https://bitbucket.org/binet/go-eval
which I salvaged from its old home exp/eval.
-s
--
#########################################
# Dr. Sebastien Binet
# Laboratoire de l'Accelerateur Lineaire
# Universite Paris-Sud XI
# Batiment 200
# 91898 Orsay
#########################################
Agreed. It's just not needed.
Although there were, IMHO, a few red herring arguments against,
there's no reason to force the Go compiler proper to recognize the
shebang in order to add _another_ compilation/run mechanism. Those
mechanisms already exists and it's little effort to customize and/or
expand them.
On a side note, the shebang is yet another Dennis Ritchie creation
(http://tinyurl.com/7luzego) - allow interpreted files to run more
like executables.
-joe
Now there's a compiler creator who didn't argue against adding script support to his program launcher…
For disenfranchised scripters, here's a demo of 3 lines of black magic:
> cat hi
#!/bin/bash
d="/tmp/$USER/.tgo/src/`basename "$0"`"&&mkdir -p "$d"&&sed 1,3d "$0"|\
(cd "$d"&&cat>"$$.go"&&go run "$$.go" "$@"<&3;s=$?;rm -f $$.go;exit $s)3<&1;exit
package main
import (
"fmt"
"os"
)
func main() {
fmt.Printf ("Hello, World. %v\n", os.Args[1:]);
}
> ./hi I do not expect some to understand this.
Hello, World. [I do not expect some to understand this.]
>
Unfortunately, gofmt barfs on the file, and "go run" does not pass stdin to the run program.
--Glenn
> For disenfranchised scripters, here's a demo of 3 lines of black magic:
>
>> cat hi
> #!/bin/bash
> d="/tmp/$USER/.tgo/src/`basename "$0"`"&&mkdir -p "$d"&&sed 1,3d "$0"|\
> (cd "$d"&&cat>"$$.go"&&go run "$$.go" "$@"<&3;s=$?;rm -f $$.go;exit $s)3<&1;exit
> package main
> import (
> "fmt"
> "os"
> )
> func main() {
> fmt.Printf ("Hello, World. %v\n", os.Args[1:]);
> }
>> ./hi I do not expect some to understand this.
> Hello, World. [I do not expect some to understand this.]
>>
>
> Unfortunately, gofmt barfs on the file, and "go run" does not pass stdin to the run program.
>
> --Glenn
Already done. From an earlier post in this thread.
$ chmod +x ./in.go
$ ./in.go
#!/usr/bin/env bash
tail -n +4 "in.go" > "out.go" && go run "out.go"
exit 0
package main
import (
"fmt"