Using go run with #!

3313 views
Skip to first unread message

Miki Tebeka

unread,
Feb 26, 2012, 11:03:25 AM2/26/12
to golan...@googlegroups.com
Greetings,

Is there a way to make the new "go run" command play with #!  (so I can have scripts)?
(And yeah, I know about goscript and gorun)

Thanks,
--
Miki

kritic

unread,
Feb 26, 2012, 11:09:47 AM2/26/12
to golang-nuts
Actually, there is a program out there called "gorun". If you use
Ubuntu you can check out the wiki here https://wiki.ubuntu.com/gorun

It allows you to run programs as "scripts" with the #!.

Pretty wicked little program.

Christoffer Hallas

unread,
Feb 26, 2012, 11:39:53 AM2/26/12
to kritic, golang-nuts
If you know about gorun and goscript, then why do you ask?

Archos

unread,
Feb 26, 2012, 1:09:02 PM2/26/12
to golang-nuts
I'm the author of goscript which was renamed to gonow(https://
github.com/kless/GoNow).

The only way that I had to run a Go program like if it were an
executable Python script was using a little trick: to checking the
first line to see if it has the shebang/hash-bang mechanism (#!); if
it's found then there are 2 options, one is copy all file excep the
first line (I did this one in my first versions), and the another one
is comment that first line, so the Go compiler can compile it.

To avoid that trick there are two ways:

(1) That the Go compiler accepts the shebang before of the package
clause. I was request it here when I was building GoNow but it was
rejected.

(2) That the bash shell (and another ones) accept "//!" like shebang
mechanism. This solution looks me very acceptable so there would be to
ask it to the maintainer of those programs.

Rémy Oudompheng

unread,
Feb 26, 2012, 1:32:48 PM2/26/12
to Archos, golang-nuts
Le 26 février 2012 19:09, Archos <raul...@sent.com> a écrit :
> (2) That the bash shell (and another ones) accept "//!" like shebang
> mechanism. This solution looks me very acceptable so there would be to
> ask it to the maintainer of those programs.

Including patching the Linux kernel itself?

Rémy.

Archos

unread,
Feb 26, 2012, 1:41:30 PM2/26/12
to golang-nuts
The patch would be simple, in "fs/binfmt_script.c". Anyway, this
solution would be only valid for Unix systems.

On Feb 26, 6:32 pm, Rémy Oudompheng <remyoudomph...@gmail.com> wrote:

John Eikenberry

unread,
Feb 26, 2012, 4:51:38 PM2/26/12
to golang-nuts
Rémy Oudompheng wrote:

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

signature.asc

Mike Rosset

unread,
Feb 26, 2012, 5:49:12 PM2/26/12
to Miki Tebeka, golan...@googlegroups.com


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

Miki Tebeka

unread,
Feb 27, 2012, 9:59:34 AM2/27/12
to golan...@googlegroups.com, kritic
I'm using "gorun" now, but I was wondering if this can be done in "pure" go toolchain.


On Sunday, February 26, 2012 8:39:53 AM UTC-8, Christoffer Hallas wrote:
If you know about gorun and goscript, then why do you ask?

Gustavo Niemeyer

unread,
Feb 27, 2012, 12:18:41 PM2/27/12
to Miki Tebeka, golan...@googlegroups.com, kritic
Hi Miki,

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.

Jens-Uwe Mager

unread,
Feb 27, 2012, 3:21:19 PM2/27/12
to golan...@googlegroups.com, Miki Tebeka, kritic
I do use gorun, and while it runs fine on tip on Linux, for OS X I had to do the following change:

$ bzr diff
=== modified file 'gorun.go'
--- gorun.go    2012-02-24 00:36:45 +0000
+++ gorun.go    2012-02-27 15:08:25 +0000
@@ -269,7 +269,7 @@
     }
     infos, err := d.Readdir(-1)
     for _, info := range infos {
-        atim := sysStat(info).Atim
+        atim := sysStat(info).Atimespec
         access := time.Unix(int64(atim.Sec), int64(atim.Nsec))
         if access.Before(cleanLine) {
             os.Remove(filepath.Join(rundir, info.Name()))

Gustavo Niemeyer

unread,
Feb 27, 2012, 5:25:45 PM2/27/12
to Jens-Uwe Mager, golan...@googlegroups.com, Miki Tebeka, kritic
Ah, thanks for the note. I'll make sure it builds out of the box for
you as well.

dlin

unread,
Feb 28, 2012, 5:59:31 AM2/28/12
to golan...@googlegroups.com
I prefer native "#!" support of Go. (Just like python).
So, the tool set about vex,fix,fmt can work on it.

There are something should be supported.

1. Go can skip first line if it is started with "#!"
2. #! /usr/bin/env gorun      # can launch it directly, here use 'gorun' instead of "go run"
3. #! /usr/bin/go run # it may be not so good, because go is not necessary to install into /usr/bin


Miki Tebeka於 2012年2月27日星期一UTC+8上午12時03分25秒寫道:

Rob 'Commander' Pike

unread,
Feb 28, 2012, 6:08:39 AM2/28/12
to dlin, golan...@googlegroups.com

On 28/02/2012, at 9:59 PM, dlin wrote:

> 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


mattn

unread,
Feb 28, 2012, 8:11:52 AM2/28/12
to golan...@googlegroups.com, Jens-Uwe Mager, Miki Tebeka, kritic
It seems that gorun does not run on windows.


But this removed some part to check UID/EUID in sysStat.

Sorry about OT.

DisposaBoy

unread,
Feb 28, 2012, 1:21:49 PM2/28/12
to golan...@googlegroups.com
FYI Python doesn't have any special support for the shebang line and neither does your shellscripts. it's a comment in the source code.

Gustavo Niemeyer

unread,
Feb 28, 2012, 1:37:09 PM2/28/12
to mattn, golan...@googlegroups.com, Jens-Uwe Mager, Miki Tebeka, kritic
On Tue, Feb 28, 2012 at 10:11, mattn <matt...@gmail.com> wrote:
> It seems that gorun does not run on windows.

That's only because Windows isn't home for Gustavo. Patches that
enable it to work without changing Linux/MacOS semantics accepted,
though.

unread,
Feb 28, 2012, 2:02:49 PM2/28/12
to golang-nuts
The Go compiler is slow for this. It would be disturbing to wait up to
1 second every time you run the script.

The idea would need a compiler cache in order to work.

André Moraes

unread,
Feb 28, 2012, 2:07:27 PM2/28/12
to golang-nuts
> The Go compiler is slow for this. It would be disturbing to wait up to
> 1 second every time you run the script.

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/

unread,
Feb 28, 2012, 2:10:00 PM2/28/12
to golang-nuts
I do not understand why he isn't expected to understand it. It is a
simple idea.

minux

unread,
Feb 28, 2012, 2:11:14 PM2/28/12
to golang-nuts


2012/2/29 André Moraes <and...@gmail.com>

> The Go compiler is slow for this. It would be disturbing to wait up to
> 1 second every time you run the script.

I think this is what Rob pointed above.
Yeah, and I think compiler speed is one design goal of Go.
And I think the gc compiler do achieve that goal (compared to gccgo).
[Of course, gccgo do provide better binaries.]

minux

unread,
Feb 28, 2012, 2:15:57 PM2/28/12
to ⚛, golang-nuts
I think he is simply making a joke citing some early Unix comment: http://swtch.com/unix/

unread,
Feb 28, 2012, 2:34:46 PM2/28/12
to golang-nuts
On Feb 28, 8:15 pm, minux <minux...@gmail.com> wrote:
It is probable you are right it was a joke related to http://swtch.com/unix/

In any case: In my opinion, recompilation of source code is a decision
that should be left to the programmer/user. The worst example is Bash:
editing the source code of a running Bash script (especially at the
beginning of the file) will probably cause a syntax error in the
running script.

Krzysztof Kowalczyk

unread,
Feb 28, 2012, 6:59:41 PM2/28/12
to Rob 'Commander' Pike, dlin, golan...@googlegroups.com
On Tue, Feb 28, 2012 at 3:08 AM, Rob 'Commander' Pike <r...@google.com> wrote:
>
> On 28/02/2012, at 9:59 PM, dlin wrote:
>
>> 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.

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

Rob 'Commander' Pike

unread,
Feb 28, 2012, 7:05:09 PM2/28/12
to Krzysztof Kowalczyk, dlin, golan...@googlegroups.com

You dropped the last sentence of my message.

-rob

Jessta

unread,
Feb 28, 2012, 7:41:05 PM2/28/12
to Krzysztof Kowalczyk, golan...@googlegroups.com
On Wed, Feb 29, 2012 at 10:59 AM, Krzysztof Kowalczyk
<kkowa...@gmail.com> > 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 #!

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

Krzysztof Kowalczyk

unread,
Feb 28, 2012, 7:46:00 PM2/28/12
to Rob 'Commander' Pike, dlin, golan...@googlegroups.com
Because I don't particularly care to decode your crypticism. I can
match anyone's snark but its Tuesday so I try to stay constructive.

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

Krzysztof Kowalczyk

unread,
Feb 28, 2012, 7:57:25 PM2/28/12
to Jessta, golan...@googlegroups.com
A little more respect to people who have different opinion than you
would be nice. Calling me (and designers and users of perl, php,
python, ruby, to name a few) "silly" is ad hominem and not
constructive.

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

Andrew Gerrand

unread,
Feb 28, 2012, 8:00:58 PM2/28/12
to Krzysztof Kowalczyk, Rob 'Commander' Pike, dlin, golan...@googlegroups.com
On 29 February 2012 11:46, Krzysztof Kowalczyk <kkowa...@gmail.com> wrote:
> Because I don't particularly care to decode your crypticism. I can
> match anyone's snark but its Tuesday so I try to stay constructive.
>
> 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.

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

Gustavo Niemeyer

unread,
Feb 28, 2012, 8:27:52 PM2/28/12
to Krzysztof Kowalczyk, Rob 'Commander' Pike, dlin, golan...@googlegroups.com
On Tue, Feb 28, 2012 at 21:46, Krzysztof Kowalczyk <kkowa...@gmail.com> wrote:
> 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.

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.

Joseph Poirier

unread,
Feb 29, 2012, 1:13:35 AM2/29/12
to Andrew Gerrand, Krzysztof Kowalczyk, Rob 'Commander' Pike, dlin, golan...@googlegroups.com
On Tue, Feb 28, 2012 at 7:00 PM, Andrew Gerrand <a...@golang.org> wrote:
> On 29 February 2012 11:46, Krzysztof Kowalczyk <kkowa...@gmail.com> wrote:
>> Because I don't particularly care to decode your crypticism. I can
>> match anyone's snark but its Tuesday so I try to stay constructive.
>>
>> 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.
>
> 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.

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

Henrik Johansson

unread,
Feb 29, 2012, 2:00:36 AM2/29/12
to golan...@googlegroups.com
I use gorun a lot for tiny scripts, i find it faster and easier to write a small bit of Go than bash or something similar.
Sure backticks and such would be handy but not a huge issue.

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?

Mike Rosset

unread,
Feb 29, 2012, 2:45:12 AM2/29/12
to Henrik Johansson, golan...@googlegroups.com
> I use gorun a lot for tiny scripts, i find it faster and easier to write a small bit of Go than bash or something similar.
> Sure backticks and such would be handy but not a huge issue.
>
> 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.

Kyle Lemons

unread,
Feb 29, 2012, 3:05:57 AM2/29/12
to Mike Rosset, Henrik Johansson, golan...@googlegroups.com
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)

Compilation speed is good, but it's still not instant.  Python, for instance, is a lot closer to instant than compiling and executing a Go executable (the bottleneck is primarily in the link step in my experience).  If you encourage programmers to write code in shell-script style, I have a strong suspicion that the "scripts" would do what python and bash scripts do--outgrow themselves.  Then when it is well past the time where it should be converted to a binary with supporting packages, the programmer will still be fighting that because it's a pain and it changes their process.  This is not a good scenario, especially when the rest of the Go ecosystem (to my mind) encourages good practices.
 
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.

unread,
Feb 29, 2012, 3:18:54 AM2/29/12
to golang-nuts
In my opinion, the following code:

#!/usr/local/bin/tcc -run
#include <stdio.h>
int main() {
    printf("Hello World\n");
    return 0;
}

can be easily converted into:

hello.c:
#include <stdio.h>
int main() {
    printf("Hello World\n");
    return 0;
}

executable file ~/bin/tcr:
#!/bin/bash
first="$1"
exe="${first%.c}"
tcc -o "${exe}" "$@"
./${exe}
rm -f "${exe}"

When you type "tcr hello.c" on the command line it compiles the C file
and runs it.

In other words, there is no need for TCC to have the -run option.

A universal "run" command that can compile&run pretty much any kind of
source code can be implemented so easily that there is very little
value to put such functionality into programming language
implementations of C, Go, Haskell or even Python:

#!run c
<<<c code>>>

#!run go
<<<go code>>>

#!run haskell
<<<haskell code>>>

#!run python
<<<python code, without #!/usr/bin/python at beginning>>>

On Feb 29, 7:13 am, Joseph Poirier <jdpoir...@gmail.com> wrote:
> On Tue, Feb 28, 2012 at 7:00 PM, Andrew Gerrand <a...@golang.org> wrote:
> > On 29 February 2012 11:46, Krzysztof Kowalczyk <kkowalc...@gmail.com> wrote:
> >> Because I don't particularly care to decode your crypticism. I can
> >> match anyone's snark but its Tuesday so I try to stay constructive.
>
> >> 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.
>
> > 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 <kkowalc...@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.
>
> 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.

Ideas are supposed to be fought with better ideas - not with
vulgarisms.

Mike Rosset

unread,
Feb 29, 2012, 3:28:46 AM2/29/12