什么是合适的Go shebang系列?

时间:2011-10-09 23:06:13

标签: go shebang

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

#!/usr/bin/env perl

Go程序的shebang是什么?

8 个答案:

答案 0 :(得分:37)

//usr/bin/go run $0 $@ ; exit

示例:

//usr/bin/go run $0 $@ ; exit
package main

import "fmt"

func main() {
    fmt.Println("Hello World!")
}

将//视为单行评论 和shell忽略额外的/

答案 1 :(得分:17)

我更喜欢这个:

///bin/true; exec /usr/bin/env go run "$0" "$@"

与هومنجاویدپور的答案相比,这有几个优点:

  • 使用'exec'替换新的shell进程,而不是启动孙进程。因此,您的Go计划将成为直接子进程。这样做效率更高,对于某些高级情况也很重要,例如调试和监控。

  • 正确引用参数。空格和特殊字符不会造成问题。

  • 领先的“///”符合标准,而不仅仅是“//”。如果仅使用“//”,则可能会遇到实现定义的行为。以下是http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html的引用:

  

如果路径名以两个连续的字符开头,则第一个   可以解释前导字符后面的组件   以实现定义的方式,虽然超过两个领先    字符应视为单个字符。

我用bash,dash,zsh和ksh测试了这个答案。

示例:

///bin/true; exec /usr/bin/env go run "$0" "$@"
package main
import "fmt"
func main() {
    fmt.Println("你好!")
}

答案 2 :(得分:13)

默认情况下没有。但是,有一个名为gorun的第三方工具可以让你这样做。 https://wiki.ubuntu.com/gorun

不幸的是编译器不喜欢shebang系列。您无法编译与gorun一起运行的相同代码。

答案 3 :(得分:9)

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

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

答案 4 :(得分:1)

到目前为止,事实证明,将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:~ $ 

答案 5 :(得分:0)

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

在我看来,到目前为止,答案的最佳组合。它使用gorun,因此它缓存了编译步骤(这大大加快了脚本的速度),并且也可以在macOS上工作。

通过以下方式安装gorun

go get github.com/erning/gorun

答案 6 :(得分:0)

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

///bin/sh -c true && exec /usr/bin/env go run "$0" "$@"

答案 7 :(得分: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")
}