大家好,关于用Go语言编写脚本的经历很多朋友都还不太明白,今天小编就来为大家分享关于的知识,希望对各位有所帮助!
Go语言的试用场景有很多,从编写Web服务器到进程管理,甚至有人将其作为系统编程语言。在下面的文章中,我将论证除了这些场景之外,Go语言还可以简单地用于编写脚本。
是什么让Go 语言适合编写脚本?
Go 语言简洁,易于阅读,而且不太冗长。这使得编写的脚本易于维护并且相对较短。 Go 语言有许多可用于各种目的的库。假设这些库稳定且经过测试,这可以使脚本保持简洁和健壮。如果我的大部分代码都是用Go 编写的,那么我更愿意使用Go 作为我的脚本语言。当代码由许多人协作维护时,通过使用每个人都可以完全控制的语言来降低维护成本,即使它只是几个脚本。
Go 语言已经 99% 支持脚本
事实上,我已经可以用Go 编写脚本了。这需要使用Go的run子命令:如果脚本名称是my-script.go,我们可以简单地通过go run my-script.go来运行它。
这里,我觉得我们需要特别注意一下go run命令。让我们详细说明一下。
Go语言与Bash和Python的区别在于后者是通过解释执行的,即它们的脚本被读取时就被执行。对于Go语言来说,当用户输入go run时,Go会编译Go程序,然后执行。因为Go 编译速度非常快,所以看起来像是解释执行。值得提醒的是,很多人说“go run 只是一个玩具”,但如果我们需要脚本并且也喜欢Go 语言,那么这个玩具就是我们想要的。
所以已经支持的很好了,对吧?
我们可以编写脚本并通过go run 命令执行它们。有哪些疑问?问题是我很懒,想通过./my-script.go 之类的东西来运行脚本,而不是go run my-script.go 。
这里我们讨论一个简单的脚本,它以两种方式与shell 交互:它从命令行获取输入数据并设置退出状态代码。这两者并不是所有可能的交互方式(此外还可以有环境变量、信号、stdin、stdout、stderr等),但它们是shell脚本中比较困难的两种方式。
此脚本打印“Hello”和从命令行获取的第一个参数,并将退出状态代码设置为42:
package main import ( ‘fmt’ ‘os’) func main() { fmt.Println(‘Hello’, os.Args[1]) os.Exit(42)} 这时候使用go run 命令会出现一些结果奇怪的:
$ go run example.go worldHello worldexit status 42$ echo $?1 我们稍后会讨论这个问题。
这时候就可以使用go build命令了。这是通过go build 命令执行脚本的方式:
$ go build$ ./example worldHello world$ echo $?42 此时,调试脚本的流程变为:
$ vim ./example.go$ go build$ ./example.go worldHi world$ vim ./example.go$ go build$ ./example.go worldBye world 我期望实现的是运行这样的脚本:
$ chmod +x example.go$ ./example.go worldHello world$ echo $?42 对应的工作流程为:
$ vim ./example.go$ ./example.go worldHi world$ vim ./example.go$ ./example.go worldBye world 似乎是一个简单的答案,对吗?
Shebang
Shebang 在类UNIX 系统上受支持。 Shebang 用于告诉shell 使用什么解释器来运行脚本。我们可以根据脚本编写的语言来设置Shebang 行。
一般来说,我们会使用env命令作为脚本执行器,这样我们就不再需要使用解释器的绝对路径了。例如:您可以将Shebang 设置为#!/usr/bin/env python 让Python 解释器运行脚本。当名为example.py 的脚本具有上述Shebang 行并且具有可执行属性(可以使用chmod +x example.py 命令添加)时,可以通过在Shell 中输入./example.py arg1 arg2 来运行它。此时Shell会读取Shebang行,然后开始连锁反应:
shell 开始运行/usr/bin/env python example.py arg1 arg2。这本质上是Shebang 行加上脚本名称加上其他参数。该命令执行/usr/bin/env,参数为/usr/bin/env python example.py arg1 arg2。然后env命令调用python命令,执行python example.py arg1 arg2。最后,python运行example.py脚本,参数为example.py arg1 arg2。
让我们首先尝试将Shebang 添加到我们的Go 脚本中。
1. 第一次天真的尝试
我们首先设置一个简单的Shebang 来使用go run 执行此脚本。添加Shebang 后的脚本如下所示:
#! /usr/bin/env go runpackage main import ( ‘fmt’ ‘os’) func main() { fmt.Println(‘Hello’, os.Args[1]) os.Exit(42)} 然后尝试运行之后一会儿,输出是:
$ ./example.go/usr/bin/env: ‘go run’ : 没有这样的文件或目录发生了什么?
Shebang机制使用go run作为env命令的参数,但这个命令实际上并不存在。输入“go run”会出现类似的错误。
2.第二次尝试
一个可能的解决方案是将Shebang 设置为#!/usr/local/go/bin/go run。在尝试之前,我们可以发现一个问题:go二进制文件在不同的系统中具有不同的路径,硬编码绝对路径会导致脚本与安装在其他位置的go不兼容。另一种解决方案是使用alias gorun=’go run’创建别名,然后将Shebang更改为#!/usr/bin/env gorun。要使用此方法,我们需要在运行此脚本的所有系统上设置此别名。
输出:
$ ./example.gopackage main:example.go:1:1: 非法字符U+0023 ‘#’ 解释:
从这个输出来看,我们有好消息也有坏消息。你想先听哪一个?先告诉你一个好消息:-)
好消息是这个解决方案是成功的,执行脚本后正常调用了go run命令。坏消息:英镑符号。在许多脚本语言中,Shebang 开头的井号作为注释被忽略。但对于Go语言编译器来说,前导井号变成了“非法字符”。 3、解决方案
当脚本不包含Shebang 行时,不同的shell 会回退到不同的解析器。 Bash 将使用自身来运行脚本,而zsh 将回退到使用sh。这给了我们一个解决方案,StackOverflow 上也提到了这个方案。
由于//是Go语言中定义的注释,我们可以使用//usr/bin/env代替/usr/bin/env(路径分隔符中为//==/),所以第一行可以设置变得:
//usr/bin/env go run ‘$0’ ‘$@’ 结果:
$ ./example.go worldHi worldexit status 42./test.go: line 2: package: 命令未找到。/test.go: line 4: 意外标记`newline’ 附近出现语法错误。/test.go: line 4: `import (‘$ echo $ ?2说明:
输出中还有一行奇怪的内容:“exit status 42”。这是什么?如果我们自己尝试一下命令我们就会明白:
$ go run ./example.go worldHello worldexit status 42$ echo $?1这是go run 命令通过标准错误输出的内容。 go run 命令屏蔽状态代码并返回状态代码1。有关此行为的讨论,请参阅Github 问题。
好的,那么其他输出行呢?这是Bash 试图解析Go 源代码,但实际上失败了。
4、方案优化
此StackOverflow 页面建议添加;exit “$?”在谢邦之后。这告诉Bash 解释器不要继续执行。
完整的舍邦:
//usr/bin/env go run ‘$0’ ‘$@’;退出“$?”结果:
$ ./test.go worldHi worldexit status 42$ echo $?1 基本实现了:这里Bash使用go run命令执行脚本,然后立即退出,并将状态码设置为go run命令后的状态码被执行。
更进一步,您可以向Shebang 行添加命令,从标准错误中删除“退出状态”内容,甚至将该文本解析为整个脚本的返回代码。
然而:
添加更多的Bash 命令意味着冗长的Shebang 行,与最初期望的#!/usr/bin/env go 相比过于复杂。请记住,这只是一个黑客,我不喜欢黑客。毕竟我们只想使用标准的Shebang 机制。为什么?因为它是如此简单、标准、优雅。这或多或少是我想找到一种更方便的语言作为脚本语言(比如Go)来替代Bash 的原因。幸运的是,我们有gorun
gorun 就是我们想要的。我们只需要在Shebang中写入#!/usr/bin/env gorun,并赋予脚本可执行权限即可。就这样,我们就可以在Shell中执行它并得到想要的结果了!
$ ./example.go worldHello world$ echo $?42 太棒了!
警告:兼容性
当文件包含shebang 时,Go 将不会编译(正如我们之前看到的)。
$ go run example.gopackage main:example.go:1:1:非法字符U+0023 ‘#’ 不能同时有两个选项,我们只能选择其一:
使用Shebang 并通过./example.go 运行脚本。或者删除Shebang 并使用go run ./example.go 运行脚本。你不能两者兼得!
最后一些想法
类型退出状态代码可执行可编译标准go rungorun //解决方案
解释:
类型:如何运行脚本。退出状态码:脚本执行后,是否设置脚本的退出状态码。可执行:脚本是否可以通过chmod +x设置可执行权限。 Compilable:脚本是否可以通过go构建。标准:脚本是否需要标准库之外的任何内容。如上图所示,目前还没有完美的解决方案。看来最方便、问题最少的方式就是使用go run 命令。但在我看来,这个方法太“复杂”且不“可执行”,而且退出状态码不正确。这将使得很难判断脚本是否正确执行。
所以我认为Go语言在这方面还有很多工作要做。我不认为让语言支持忽略Shebang 行有什么问题。这将解决实现问题,但这样的更改可能不会被Go 社区采用。
我的同事提醒我,Shebang 行实际上对于Javascript 来说也是非法的。但在Node.js中,他们添加了skip Shebang功能,以便Node脚本可以直接在Shell中运行。 (译者注:由于原文已相当旧,Node.js在c2b01881dcb3bf302f9d83157e719cc5240a9042版本之后重构了源码。702331be906fe58e0ef66c7b31c7d2aeb3af3421版本之后,原文中提到的stripShebang函数已被删除。)
如果gorun 能够与gofmt 和godoc 一起成为标准工具的一部分,那就太好了。
原文链接:
原创文章,作者:小su,如若转载,请注明出处:https://www.sudun.com/ask/175252.html
用户评论
墨染年华
刚开始接触Go,感觉简洁明了,比之前用的python快很多!这次写脚本真的体验感好,编译速度也飞快,简直太棒了!
有10位网友表示赞同!
一笑傾城゛
虽然Go 的语法简单,但是对于我来说还是有些新奇的地方需要慢慢学习摸索。不过这个脚本写的思路很清晰,读起来还行,可以借鉴一下。
有14位网友表示赞同!
花海
第一次用Go语言写脚本挺有趣儿,感觉比其它語言容易上手不少,尤其是数据处理和并发部分,Go确实很有优势,打算以后多利用它来写一些小的工具.
有20位网友表示赞同!
仅有的余温
这篇文章写的不错,介绍的Go语言的优缺点比较全面,让我对Go语言有了更深入的理解。我正在学习Go语言,这篇blog对我来说很实用!
有15位网友表示赞同!
将妓就计
感觉Go 的语法还是比较简洁易懂的,但对于新手来说,环境配置和工具链可能稍微有些复杂。总体来说脚本写得还不错,思路清晰可读性强。
有9位网友表示赞同!
凉月流沐@
Go 的性能一直是被吹捧的优势,但这篇文章中关于Go语言编写脚本的体验描述更像是在歌颂它的简单易用性。确实,Go 对于快速开发这种小型脚本很有帮助,但并不是说它适合所有类型的脚本编写场景, 还是得根据实际情况选择合适的工具。
有18位网友表示赞同!
堕落爱人!
脚本写的真的很有深度,虽然我目前还没接触过Go语言,但是阅读代码逻辑能清晰地理解作者的思路。学习语言的过程确实需要不断实践和尝试,期待有一天我也能写出像这样实用的代码!
有18位网友表示赞同!
墨城烟柳
对于已经熟悉多种语言的程序员来说,Go 语言并不算难上手,这篇博客里提到的 Golang 特点和使用体验非常实用,对正在学习Go语言的朋友们很有帮助!
有6位网友表示赞同!
黑夜漫长
我觉得 Go 语言在性能稳定性方面确实很优秀,但对于一些需要频繁交互或者调用的脚本功能来说,它可能显得有些笨重。当然这得看项目需求了。
有10位网友表示赞同!
那伤。眞美
文章写的非常详细,将Go语言编写脚本的过程和需要注意的地方都描述了很清楚, 对于初学者来说很有帮助!
有10位网友表示赞同!
折木
感觉文章描述的Go语言的优势有点过分宣传了,实际应用中,总有一些局限性。比如对于一些需要高度定制化的场景,Go语言可能不够灵活。
有13位网友表示赞同!
苏樱凉
第一次尝试用Go语言编写脚本,感觉它的类型系统很有帮助。代码写的更加清晰易懂,维护起来也更方便!
有9位网友表示赞同!
﹎℡默默的爱
我是一个Python开发者,一直在寻找一种性能更高的方式来实现我的脚本任务。最近开始学习 Go 语言,这本书提供了很好的入门指南, 文章中涉及的例子也十分实用.
有10位网友表示赞同!
柠栀
Go语言确实很强大,但对于一些需要大量调用外部API的任务来说,他的缺点可能更为明显。比如,Go的HTTP库相比Python中的requests库功能相对较少。需要开发者自己去拼凑实现, 整体开发效率可能会降低。
有10位网友表示赞同!
相知相惜
我觉得脚本写的不错, 但Go语言的并发机制对新手来说有点复杂, 需要多加练习才能真正理解和掌握。
有8位网友表示赞同!
泡泡龙
这篇博客分享的可视化效果真的很棒!用图表展示Go语言使用场景和特点,让文章内容更生动有趣, 帮助读者快速掌握关键信息。
有20位网友表示赞同!