Shebang starting with `//`?
It isn't a shebang, it is just a script that gets run by the default shell. The shell executes the first line
//usr/bin/env go run $0 $@ ; exit
which causes go
to be invoked with the name of this file, so the result is that this file is run as a go script and then the shell exits without looking at the rest of the file.
But why start with //
instead of just /
or a proper shebang #!
?
This is because the file need to be a valid go script, or go will complain. In go, the characters //
denote a comment, so go sees the first line as a comment and does not attempt to interpret it. The character #
however, does not denote a comment, so a normal shebang would result in an error when go interprets the file.
This reason for the syntax is just to build a file that is both a shell script and a go script without one stepping on the other.
It runs because by default executable file is assumed to be /bin/sh script. I.e. if you didn't specify any particular shell - it is #!/bin/sh.
The // is just ignored in paths - you can consider is at as single '/'.
So you can consider that you have shell script with first line:
/usr/bin/env go run $0 $@ ; exit
What does this line do? It runs 'env' with paramenters 'go run $0 $@'. there 'go' is command and 'run $0 $@' are args and exits script afterwards. $0 is this script name. $@ are original script arguments. So this line runs go which runs this script with it's arguments
There are quite interesting details, as pointed in comments, that two slashes are implementation-defined, and this script would become POSIX-correct if it specify three or more slashes. Refer to http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html for details on how slashes should be handled in paths.
Note also that there is another mistake in script the $@ it's correct to use "$@" instead, because otherwise if any parameter contains spaces it will be split to many parameters. For example you can't pass file name with spaces if you not using the "$@"
This particular script obviously rely on the idea that '//' is equal to '/'