Go - 2.命令源码文件

目录

一.引言

二.命令源码文件

1.什么是 `命令源码文件` ?

2.`命令源码文件` 示例

三.程序扩展

1.代码框架

2.代码分析

3.代码运行

四.源码文件参数说明

1.使用 -help 

2.自定义源码参数文件说明 

3.参数进阶

五.总结


一.引言

上文我们安装了 Go 语言的安装包,本文我们主要了解什么是命令源码文件,并执行自己的第一个 go 代码。

二.命令源码文件

1.什么是 `命令源码文件` ?

命令源码文件是程序的运行入口,是每个可独立运行的程序必须拥有的。我们可以通过构建或安装,生成与其对应的可执行文件,后者一般会与该命令源码文件的直接父目录同名。

2.`命令源码文件` 示例

- GoLand 执行

如果一个源码文件声明属于main包,并且包含一个无参数声明且无结果声明的main函数,那么它就是命令源码文件。 就像下面这段代码:

package main

import "fmt"

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

在 GoLand 根目录下创建 TestMain.go 文件添加上述代码并运行即可获得下述结果:

 - Terminal 执行

直接在 Terminal 中例如 Iterm 中输入:

go run TestMain.go

同样可以获取下述结果:

- Tips

当需要模块化编程时,我们往往会将代码拆分到多个文件,甚至拆分到不同的代码包中。但无论怎样,对于一个独立的程序来说,命令源码文件永远只会也只能有一个。如果有与命令源码文件同包的源码文件,那么它们也应该声明属于 main 包。

三.程序扩展

1.代码框架

执行 Hello World 只是开始,下面我们尝试执行更复杂的任务,我们接收参数 name 并向 name 打招呼,下面我们基于代码框架进行填空操作。

package main

import (
  // 需在此处添加代码。[1]
  "fmt"
)

var name string

func init() {
  // 需在此处添加代码。[2]
}

func main() {
  // 需在此处添加代码。[3]
  fmt.Printf("Hello, %s!\n", name)
}

2.代码分析

首先,Go 语言标准库中有一个代码包专门用于接收和解析命令参数,这个代码包的名字叫 flag

如果想要在代码中使用某个包中的程序实体,那么应该先导入这个包。因此:

我们需要在 [1] 处添加代码 "flag"

注意,这里应该在代码包导入路径的前后加上英文半角的引号。如此一来,上述代码导入了 flag 和 fmt 这两个包。其次,人名肯定是由字符串代表的。所以我们要在 [2] 处添加调用 flag 包的 StringVar 函数的代码。就像这样:

flag.StringVar(&name, "name", "everyone", "The greeting object.")

顺便说一下,还有一个与 flag.StringVar 函数类似的函数,叫 flag.String。这两个函数的区别是,后者会直接返回一个已经分配好的用于存储命令参数值的地址。如果使用它的话,我们就需要做如下改动,不过这里我们使用前者

再说最后一个填空。我们需要在 [3] 处添加代码 flag.Parse()。函数 flag.Parse 用于真正解析命令参数,并把它们的值赋给相应的变量。对该函数的调用必须在所有命令参数存储载体的声明(这里是对变量 name 的声明)和设置(这里是在 [2] 处对 flag.StringVar 函数的调用)之后,并且在读取任何命令参数值之前进行。正因为如此,我们最好把 flag.Parse() 放在 main 函数的函数体的第一行。 有过 Java、Scala 或者 Python 开发经验的同学,这里就像他们的 Sys.args 一样,用于接收我们外部的传参。

3.代码运行

填空后的代码如下:

package main

import (
	"flag"
	"fmt"
)

var name string

func init() {
	flag.StringVar(&name, "name", "everyone", "The greeting object.")
}

func main() {
	flag.Parse()
	fmt.Printf("Hello, %s!\n", name)
}

我们的程序目的是接收 $name 参数,并向 $name 打招呼,在命令行执行下述命令:

go run TestFlag.go -name="BITDDD"

四.源码文件参数说明

1.使用 -help 

go run TestFlag.go -help

传入 -help 参数获取相关参数说明:

第一行 Usage 开头的是 `go run` 命令构建上述命令源码文件时临时生成的可执行文件的完整路径。 如果我们先构建这个命令源码文件再运行生成的可执行文件,像这样:

go build TestFlag.go 
./TestFlag -help

我们的 Usage 地址就切换了,因为已经通过 build 在本地生成了:

2.自定义源码参数文件说明 

这有很多种方式,最简单的一种方式就是对变量 flag.Usage 重新赋值。flag.Usage 的类型是func(),即一种无参数声明且无结果声明的函数类型。

flag.Usage 变量在声明时就已经被赋值了,所以我们才能够在运行命令 go run xx.go --help 时看到正确的结果。注意,对 flag.Usage 的赋值必须在调用 flag.Parse 函数之前。

package main

import (
	"flag"
	"fmt"
	"os"
)

var name string

func init() {
	flag.StringVar(&name, "name", "everyone", "The greeting object.")
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", "question")
		flag.PrintDefaults()
	}
	flag.Parse()
	fmt.Printf("Hello, %s!\n", name)
}

再次执行 -help 可以看到 Usage 的名称也会对应的改变:

3.参数进阶

现在再深入一层,我们在调用 flag 包中的一些函数(比如StringVar、Parse等等)的时候,实际上是在调用 flag.CommandLine 变量的对应方法。flag.CommandLine 相当于默认情况下的命令参数容器。所以,通过对 flag.CommandLine 重新赋值,我们可以更深层次地定制当前命令源码文件的参数使用说明。再进一步,我们索性不用全局的 flag.CommandLine 变量,转而自己创建一个私有的命令参数容器。

package main

import (
	"flag"
	"fmt"
	"os"
)

var name string
var source string
var cmdLine = flag.NewFlagSet("question", flag.ExitOnError)

func init() {
	cmdLine.StringVar(&name, "name", "everyone", "The greeting object.")
	cmdLine.StringVar(&source, "source", "none", "The greeting source.")
}

func main() {
	cmdLine.Parse(os.Args[1:])
	fmt.Printf("Hello, %s from %s!\n", name, source)
}

其中的 os.Args[1:] 指的就是我们给定的那些命令参数。这样做就完全脱离了 flag.CommandLine。*flag.FlagSet 类型的变量 cmdLine 拥有很多有意思的方法,你可以去探索一下。这样做的好处依然是更灵活地定制命令参数容器。但更重要的是,你的定制完全不会影响到那个全局变量flag.CommandLine。 

五.总结

现在我们已经走出了 Go 语言编程的第一步,我们可以使用 Go 编写命令,可以通过 Go Build 构建可执行的 .go 文件直接运行,并且可以通过命令行传参。继续加油 💪🏻

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIT_666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值