Go语言36讲笔记--02命令源码文件

245 阅读4分钟

这里介绍的是每个工作区中,以代码包为基本组织形式的源码文件

源码文件分三种:命令源码文件、库源码文件、测试源码文件。三者有不同的用途和编写规则。

命令源码文件

what:命令源码文件是程序的运行入口,是每个可独立运行的程序必须拥有的。我们可以通过构建或安装,生成与其对应的可执行文件,后者一般会与该命令源码文件的直接父目录同名。
how:如果一个源码文件声明属于main包,并且包含一个无参数声明且无结果声明的main函数,那么它就是命令源码文件。
举个栗子:就像下面这段代码

package main

import "fmt"

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

如果你把这段代码存成 demo1.go 文件,那么运行go run demo1.go命令后就会在屏幕(标准输出)中看到Hello, world!

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

命令参数的接收和解析:几乎所有命令(command)都是可以接收参数(argument)的。

what(命令):通过构建或安装命令源码文件,生成的可执行文件就可以被视为“命令”,既然是命令,那么就应该具备接收参数的能力。无论是 Linux 还是 Windows,如果你用过命令行(command line)的话,肯定就会知道几乎所有命令(command)都是可以接收参数(argument)的。

命令源码文件怎么接收参数
看一段代码

package main

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

var name string

func init() {//这个init函数不必在main中调用,在这里定义好就行
	// 需在此处添加代码。[2]
	flag.StringVar(&name, "name", "everything", "The greeting object")
}

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

Go 语言标准库中有一个代码包专门用于接收和解析命令参数。这个代码包的名字叫flagflag.StringVar(&name, "name", "everyone", "The greeting object.")

参数1:上面声明过的变量的地址,用于存储该命令参数值
参数2:用于指定参数的名称
参数3:默认参数
参数4:打印命令说明
关于flag.StringVarflag.String的区别: 后者返回一个分配好地址的参数实体
关于函数flag.Parse what: 用于真正解析命令参数,并把它们的值赋给相应的变量。
how: 对该函数的调用必须在所有命令参数存储载体的声明(这里是对变量name的声明)和设置(这里是在[2]处对flag.StringVar函数的调用)之后,并且在读取任何命令参数值之前进行。正因为如此,我们最好把flag.Parse()放在main函数的函数体的第一行。

怎样在命令源码文件执行的时候传参,怎样查看参数的使用说明
两个问题,执行的时候怎么传参&怎么查看参数声明
举个栗子(关于传参)

输入命令,go run test.go -name="STY", 结果Hello, STY!

举个栗子(关于查看参数声明)

输入命令,go run test.go --help
返回结果是:

Usage of C:\Users\90682\AppData\Local\Temp\go-build600599929\b001\exe\test.exe:
  -name string
        The greeting object (default "everything")

这其实是go run命令构建上述命令源码文件时临时生成的可执行文件的完整路径
如果我们先构建这个命令源码文件再运行生成的可执行文件

>go build test.go
A:\goWorkAreas\src\test>test --help
Usage of test:
  -name string
        The greeting object (default "everything")

怎样自定义命令源码文件的参数使用说明(即对参数使用说明更为详细的定制化)


总结

可以用 Go 编写命令,并可以让它们像众多操作系统命令那样被使用,甚至可以把它们嵌入到各种脚本中。
思考题

  1. 默认情况下,我们可以让命令源码文件接受哪些类型的参数值?

这个问题查看flag库文件中的具体函数类型就可以flag.IntVar/flag.BoolVar/flag.StringVar...

  1. 我们可以把自定义的数据类型作为参数值的类型吗?如果可以,怎样做?(怎样声明自己的数据类型)