可以将Go代码作为脚本运行吗?

huangapple go评论86阅读模式
英文:

Is it possible to run Go code as a script?

问题

随着Go语言成为“系统”的语言,我想知道是否有可能在不编译的情况下将Go代码作为脚本运行,是否有可能做到这一点?

以下是要翻译的内容:

随着Go语言成为“系统”的语言,我想知道是否有可能在不编译的情况下将Go代码作为脚本运行,是否有可能做到这一点?

动机(因为有人问到动机),引用自如何将Scala用作脚本语言

问题:您希望在Unix系统上将Scala用作脚本语言,以替换您在Unix shell(Bourne Shell、Bash)、Perl、PHP、Ruby等中编写的其他脚本。

更新:
我想知道我能够如何“滥用”go run来使大量的Go代码作为“脚本”运行,尽管它是经过编译的(我喜欢它是经过编译的),但看起来go run可以给我替代“脚本”的机会,即在服务器上拥有源文件并将它们作为源代码运行,同时由go run进行编译,但我仍然管理源文件而不是可执行文件。

更新:
此外,我还看到了gorun

gorun - 用于Go源文件的类似脚本的运行器。

尽管有动机和工具试图解决无法作为脚本运行的问题,但我不会选择这种方式,+有人告诉我它还没有准备好投入生产,并建议我不要在生产环境中使用它,因为它还没有准备好投入生产,它已经超出了它的用途,并且需要放弃脚本的便利性以换取Go的优势。(我对编译、静态类型没有任何意见,我是它的忠实粉丝,但我希望有一些类似脚本的便利性)。

英文:

As Go is becoming the language of the "system". I wonder if it's possible to run Go code as a script, without compiling it, is there any possibility to do that?

The motivation (as there were questions as for motivation), taken from How to use Scala as a scripting language

> Problem You want to use Scala as a scripting language on Unix systems,
> replacing other scripts you’ve written in a Unix shell (Bourne Shell,
> Bash), Perl, PHP, Ruby, etc.

UPDATE:
I wonder how much I can "abuse" go run to be able to have much Go code running as scripts though compiled (which I like that its compiled) but it looks like go run can give me the opportunity to replace scripting, that is have source files on servers and run them as source while getting compiled by the go run but I still manage sources and not executables.

UPDATE:
in addition saw gorun

> gorun - Script-like runner for Go source files.

Though there is a motivation and tools which tried to workaround not being able to run as script, I will not go for it, +I've been told it's not production ready and was advised not to use it in production because it's not production ready, it's out of it's purpose and would need dump the scripting convenience in favour of Go. (I don't have anything against compiling, static typing, I'm a big fan of it, but wanted something similar to scripting convenience).

答案1

得分: 19

我不是go的专家,但你可以这样做。我知道这不够优雅,但可能是一个开始的地方 可以将Go代码作为脚本运行吗?

package main

import "fmt"

func main() {
    fmt.Printf("Hello World\n")
}

你可以将以上代码保存为vikas.go文件,然后在命令行中运行go run vikas.go来执行它。执行结果应该是输出Hello World

英文:

I am not an expert in go, but you can do something like this. I know this is not elegant, but may be something to start with 可以将Go代码作为脚本运行吗?

~$ cat vikas.go
//usr/bin/env go run "$0" "$@"; exit

package main

import "fmt"

func main() {
	fmt.Printf("Hello World\n")
}
~$

~$ ./vikas.go
Hello World
~$

答案2

得分: 9

正如其他人所指出的,Go是一种编译语言。使用Go语言编写的程序依赖于添加到可执行二进制文件中的Go运行时。

Go运行时提供了一些重要的功能,如垃圾回收、goroutine调度、运行时反射等。没有这些功能,Go应用程序无法按照语言规范保证正常工作。

一个“理论上的”Go解释器将需要模拟这些功能,这基本上意味着需要包含一个Go运行时和一个Go编译器。目前并没有这样的解释器,也没有这个必要。
还要注意的是,如果代码尚未编译,那么Go解释器将需要包含整个标准库,因为Go“脚本”可以合法地引用标准库中的任何内容(当Go应用程序被编译时,只有它使用/引用的内容才会被编译到可执行二进制文件中)。

要快速测试一些东西,只需使用go run命令,它会编译你的应用程序并在临时文件夹中构建一个可执行二进制文件,然后启动该临时文件,并在应用程序退出时清理它。

其他人发布的“解决方案”可能“感觉”像脚本,但实际上它们只是自动化/隐藏了将Go源代码编译为可执行二进制文件,然后启动该二进制文件的过程。这正是go run命令所做的(它还会清理临时二进制文件)。

英文:

As others noted, Go is a compiled language. Programs written in the Go language rely on the Go runtime which is added to the executable binary.

The Go runtime provides certain vital features such as garbage collection, goroutine scheduling, runtime reflection etc. Without them a Go app cannot work as guaranteed by the language spec.

A theoretical Go interpreter would have to simulate those features, which would essentially mean to include a Go runtime and a Go compiler. There is no such thing, and there is no need for that.
Also note that if the code is not yet compiled, that means the Go interpreter would have to contain all the standard library, because a Go "script" could legally refer to anything from the standard library (when a Go app is compiled, only things that it uses / refers to gets compiled into the executable binary).

To quickly test something, just use go run, which also compiles your app and builds an executable binary in a temporary folder, launches that temp file and cleans it when your app exits.

"Solutions" posted by others may "feel" like scripting, but they are nothing more than automating / hiding the process of compiling the Go source to an executable binary and then launching that binary. This is exactly what go run does (which also cleans up the temporary binary).

答案3

得分: 8

在Linux上完全可以实现,感谢cf的贡献:https://blog.cloudflare.com/using-go-as-a-scripting-language-in-linux

如果你不想使用已经提到的可能有限制的"shebang",可以这样做:

//usr/bin/env go run "$0" "$@"; exit "$?"

而是这样做:

# 检查binfmt_misc是否已经激活
# (应该已经通过systemd完成)
mount | grep binfmt_misc

# 如果还没有挂载
sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc

# 获取gorun并将其放置在可以工作的位置
go get github.com/erning/gorun
sudo mv $GOPATH/bin/gorun /usr/local/bin

# 使.go脚本使用`gorun`包装脚本运行
echo ':golang:E::go::/usr/local/bin/gorun:OC' | sudo tee /proc/sys/fs/binfmt_misc/register

这只是用于一次性测试。要使其持久化,我将这行代码作为/etc/rc.local文件中倒数第二行:

echo ':golang:E::go::/usr/local/bin/gorun:OC' | tee /proc/sys/fs/binfmt_misc/register 1>/dev/null

如果在开发脚本过程中遇到类似"缓存"问题,可以查看/tmp/gorun-$(hostname)-USERID

我喜欢bash,但是一旦你需要一个合适的数据结构(由于不可用性,bash数组和关联数组不算),你就需要另一种语言。
对我来说,使用Golang编写比使用Python更快,上述的任何Golang设置对我来说都可以。不需要为了python 2和3之间的问题而奋斗,不需要处理其库和pip的问题,可以随意分发二进制文件,并且可以立即更改源代码以用于一次性小脚本,这就是为什么这种方法绝对有其优势的原因。

英文:

Absolutely possible on linux, props to cf: https://blog.cloudflare.com/using-go-as-a-scripting-language-in-linux

In case you don't want to use the already mentioned 'shebang' which may have limitations:

//usr/bin/env go run "$0" "$@"; exit "$?"

Do this instead:

# check if binfmt_misc is already active 
# (should already be done through systemd)
mount | grep binfmt_misc

# if not already mounted
sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc

# get gorun and place it so it will work
go get github.com/erning/gorun
sudo mv $GOPATH/bin/gorun /usr/local/bin

# make .go scripts being run with `gorun` wrapper script
echo ':golang:E::go::/usr/local/bin/gorun:OC' | sudo tee /proc/sys/fs/binfmt_misc/register

This is just for one-off testing. To make this persistant, I have this as the second last line in my /etc/rc.local's:

echo ':golang:E::go::/usr/local/bin/gorun:OC' | tee /proc/sys/fs/binfmt_misc/register 1>/dev/null

If you experience something like 'caching' issues during developing scripts, have a look at /tmp/gorun-$(hostname)-USERID.

I love bash, but as soon as you need a proper datastructures (bash arrays and associative arrays don't count due to unusability) you need another language.
Golang is faster to write for me than is python, and any golang setup as depicted above will do for me. No battling python 2 vs 3, its libs and pip horrors, have a distributable binary at will, and just instantly be able to change the source for small one-off scripts is why this approach has definitely its upsides.

答案4

得分: 3

请看Neugram,Go脚本。以下是它的文档:

#!/usr/bin/ng

// 启动一个用于提供文件的Web服务器。
import "net/http"
pwd := $$ echo $PWD $$
h := http.FileServer(http.Dir(pwd))
http.ListenAndServe(":8080", h)
英文:

see Neugram, Go scripting . From it's documentation:

#!/usr/bin/ng

// Start a web server to serve files.
import "net/http"
pwd := $$ echo $PWD $$
h := http.FileServer(http.Dir(pwd))
http.ListenAndServe(":8080", h)

答案5

得分: -6

不,这既不可能也不可取。

英文:

No this is neither possible nor desirable.

huangapple
  • 本文由 发表于 2017年1月9日 15:27:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/41542941.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定