我喜欢使用 shebangs 直接运行我的 Perl 脚本:
#!/usr/bin/env perl
Go 程序的 shebang 是什么?
//usr/bin/go run $0 $@ ; exit
例子:
//usr/bin/go run $0 $@ ; exit
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
}
go 将//
其视为单行注释,shell 忽略额外的/
更新:Go 安装可能在不同的位置。下面的语法将考虑到这一点,适用于 Mac:
//$GOROOT/bin/go run $0 $@ ; exit
我更喜欢这个:
///usr/bin/true; exec /usr/bin/env go run "$0" "$@"
与هومنجاویدپور的答案相比,这有几个优点:
完成了同时是有效的 Go 和 shell 语法的///usr/bin/true
壮举。在 Go 中,它是一个注释。在 shell 中,它是无操作命令。
用于exec
替换新的 shell 进程而不是启动孙进程。因此,您的 Go 程序将是一个直接的子进程。这更有效,对于一些高级情况也很重要,例如调试和监控。
正确引用论据。空格和特殊字符不会引起问题。
领先///
的标准不仅仅是//
. 如果只使用//
,则可能会遇到实现定义的行为。这是来自http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html的引述:
如果路径名以两个连续字符开头,则可以以实现定义的方式解释
/
前导字符之后的第一个组件,尽管应将两个以上的前导字符视为单个字符。/
/
/
我已经用 bash、dash、zsh 和 ksh 测试了这个答案。
例子:
///usr/bin/true; exec /usr/bin/env go run "$0" "$@"
package main
import "fmt"
func main() {
fmt.Println("你好!")
}
默认没有一个。不过,有一个名为 gorun 的第三方工具可以让您执行此操作。https://wiki.ubuntu.com/gorun
不幸的是,编译器不喜欢 shebang 行。您无法编译使用 gorun 运行的相同代码。
Go 程序被编译成二进制文件;我认为没有直接从源代码运行它们的选项。
这类似于其他编译语言,例如 C++ 或 Java。某些语言(例如 Haskell)提供完全编译模式和“脚本”模式,您可以使用 shebang 行直接从源代码运行。
/// 2>/dev/null; gorun "$0" "$@" ; exit $?
在我看来,迄今为止答案的最佳组合。它使用gorun
它缓存编译步骤(这大大加快了您的脚本),并且也适用于 macOS。
安装gorun
:
go get github.com/erning/gorun
就我而言,没有 GOROOT 环境。所以我做了这个。
//$(go env | grep -i goroot | awk -F= '{print $2}' | sed 's/\"//g')/bin/go run $0 $@ ; exit
如果你真的想要一个可执行文件(不能从 shell 调用)并且不想要求 gorun 一个可能的解决方案可能是这样的:
#!/bin/sh
UMASK=`umask`
umask 077
tail -n +8 "$0" > /tmp/main.tmp.$$.go
umask $UMASK
(sleep 1 && rm -f /tmp/main.tmp.$$.go) &
exec go run /tmp/main.tmp.$$.go "$@"
package main
import "fmt"
func main() {
fmt.Println("hi")
}
到目前为止,链接 sh 和 gorun 已被证明是对我来说最便携的解决方案。
///bin/sh -c true && exec gorun "$0" "$@"
package main
import (
"fmt"
"log"
"os"
)
func main() {
fmt.Println("hello")
log.Printf("args: %v", os.Args)
// just to test exit code, would be 0x11
os.Exit(17)
}
输出:
00:~ $ chmod a+x test.go && ./test.go rawr
hello
2020/01/21 23:17:40 args: [./test.go rawr]
11:~ $
阅读所有这些消息,这似乎是最便携的:
///bin/sh -c true && exec /usr/bin/env go run "$0" "$@"