45

我喜欢使用 shebangs 直接运行我的 Perl 脚本:

#!/usr/bin/env perl

Go 程序的 shebang 是什么?

4

9 回答 9

43

//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

于 2013-07-27T18:10:22.467 回答
37

我更喜欢这个:

///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("你好!")
}
于 2015-05-06T16:49:00.480 回答
16

默认没有一个。不过,有一个名为 gorun 的第三方工具可以让您执行此操作。https://wiki.ubuntu.com/gorun

不幸的是,编译器不喜欢 shebang 行。您无法编译使用 gorun 运行的相同代码。

于 2011-10-09T23:37:03.457 回答
9

Go 程序被编译成二进制文件;我认为没有直接从源代码运行它们的选项。

这类似于其他编译语言,例如 C++ 或 Java。某些语言(例如 Haskell)提供完全编译模式和“脚本”模式,您可以使用 shebang 行直接从源代码运行。

于 2011-10-09T23:08:40.430 回答
0

/// 2>/dev/null; gorun "$0" "$@" ; exit $?

在我看来,迄今为止答案的最佳组合。它使用gorun它缓存编译步骤(这大大加快了您的脚本),并且也适用于 macOS。

安装gorun

go get github.com/erning/gorun

于 2020-08-26T19:46:03.043 回答
0

就我而言,没有 GOROOT 环境。所以我做了这个。

//$(go env | grep -i goroot | awk -F= '{print $2}' | sed 's/\"//g')/bin/go run $0 $@ ; exit
于 2022-02-02T19:13:36.123 回答
0

如果你真的想要一个可执行文件(不能从 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")
}
于 2021-07-28T18:27:46.067 回答
0

到目前为止,链接 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:~ $ 
于 2020-01-22T05:26:00.940 回答
0

阅读所有这些消息,这似乎是最便携的:

///bin/sh -c true && exec /usr/bin/env go run "$0" "$@"
于 2021-07-19T10:23:01.533 回答