go学习笔记(二)——命令源码文件

 

注:命令源码文件:如果一个源码文件声明属于main包,并且包含一个无参数声明的main函数,那么他就是命令源码文件。

将代码拆分到多个文件,甚至拆分到不同的代码包中。但是,命令源文件永远只有一个,也就是只有一个main函数入口。

如果有与命令源文件同包的源码文件,那么他们也应该声明属于main包(package main)

  • 1.命令源码文件怎样接收参数

知识点:Go标准库中,有一个flag库专门用于接受和解析命令参数。

其中StringVar函数用来接受字符串参数,String函数直接返回已经分配好的用于存储命令参数值的地址,用法不同:

flag.StringVar(&name, "name", ...)

flag.String("name", ...)

这里使用StringVar函数处理,示例,demo2.go

// demo2.go
package main
 
import (
        "flag"
        "fmt"
)
 
var StudentName string
 
//初始化函数,编译时自动调用
func init() {
        flag.StringVar(&StudentName,
                "name", "Default Name",
                "This is student depart \ndescription.")
}
 
func main() {
        flag.Parse() // 解析命令参数,并把值赋给变量 StudentName
        fmt.Printf("Hello, %s!\n", StudentName)
}

说明一下StringVar函数的参数列表:

第一个参数是用于存储该命令参数的值的地址,用符号“&”表示,这里取“&StudentName”

第二个参数指定了该命令参数的名称,这里是“name”,使用方法“-name”

第三个参数指定了未追加该命令参数时的默认值,这里是“Default Name”

第四个参数指的是该命令参数的描述

  • 2.怎样在运行命令源码文件时传参,查看参数使用说明

上述文件报存为demo2.go,在运行如下命令就可以为参数name传值:

go run demo2.go -name="Steven"

运行结果:

$ go run demo2.go -name="Steven"

Hello, Steven!

前面提到过第四个参数为参数说明,可以运行“--help”查看,比如: go run demo2.go --help

go run demo2.go --help

Usage of /tmp/go-build084670678/b001/exe/demo2:

-name string

This is student depart

description. (default "Default Name")

exit status 2

其中有一段输出“/tmp/go-build084670678/b001/exe/demo2”, 指的是 go run 命令构建源码文件时生成的临时文件的完整路径。

接下来,我们可以构建(build)源码文件,并生成可执行文件了,比如:

[root@localhost example]# go build demo2.go

[root@localhost example]# ./demo2 --help




那么输出就会是:
Usage of ./demo2:

-name string

This is student depart

description. (default "Default Name")

试着把参数增加到两个试试运行结果:

  •  3.怎样自定义命令源码文件的参数使用说明

知识点:flag.Usage的类型是func(),是一种无参数声明且无结果声明的函数类型,也可以作为变量,它在声明时就被赋值。

如果要自定义参数使用说明,对flag.Usage的赋值就必须在flag.Parse前。

下面来看示例,demo3.go(注意要导入os库):

  1. // demo3.go

  2. package main

  3.  
  4. import (

  5. "flag"

  6. "fmt"

  7. "os"

  8. )

  9.  
  10. var StudentName string

  11.  
  12. //初始化函数,编译时自动调用

  13. func init() {

  14. flag.StringVar(&StudentName,

  15. "name", "Default Name",

  16. "This is student depart \ndescription.")

  17. }

  18.  
  19. func main() {

  20. flag.Usage = func() {

  21. fmt.Fprintf(os.Stderr, "Usage of %s:\n", "question")

  22. flag.PrintDefaults()

  23. }

  24. flag.Parse()

  25. fmt.Printf("Hello, %s!\n", StudentName)

  26. }

运行后,会发现代替了之前的输出:

 
  1. [root@localhost example]# go run demo3.go --help

  2. Usage of question:

  3. -name string

  4. This is student depart

  5. description. (default "Default Name")

  6. exit status 2

知识点:flag.CommandLine变量也是一种func()类型,当我们在调用StringVar,Parse时,其实就是在调用该变量的对应方法,其就相当于默认情况下的命令参数“容器”。

下面,我们再次来实践下,demo3-1.go:

  1. // demo3-1.go

  2. package main

  3.  
  4. import (

  5. "flag"

  6. "fmt"

  7. "os"

  8. )

  9.  
  10. var StudentName string

  11.  
  12. //初始化函数,编译时自动调用

  13. func init() {

  14. flag.StringVar(&StudentName,

  15. "name", "Default Name",

  16. "This is student depart \ndescription.")

  17. }

  18.  
  19. func main() {

  20. flag.CommandLine = flag.NewFlagSet("", flag.ExitOnError)

  21. flag.CommandLine.Usage = func() {

  22. fmt.Fprintf(os.Stderr, "Usage of %s:\n", "question")

  23. flag.PrintDefaults()

  24. }

  25. flag.Parse()

  26. fmt.Printf("Hello, %s!\n", StudentName)

  27. }

这样的定制方式更灵活,还可以改为:

flag.CommandLine=flag.NewFlagSet("", flag.PanicOnError)

其中flag.PanicOnError和flag.ExitOnError都是预定义在flag包中的常量。

ExitOnError告诉命令参数容器,如果参数设置不正确的时候,以状态码2(表示用户使用了错误的命令)结束当前程序。

PanicOnError指的是最后抛出“运行时恐慌(panic)-一种Go语言在程序错误处理方面的概念”。

接下来,我们采用自己创建一个私有的命令参数“容器”,在main函数外先增加一个变量声明:

  1. // demo3-2.go

  2. package main

  3.  
  4. import (

  5. "flag"

  6. "fmt"

  7. "os"

  8. )

  9.  
  10. var StudentName string

  11. var cmdLine = flag.NewFlagSet("question", flag.ExitOnError)

  12.  
  13. //初始化函数,编译时自动调用

  14. func init() {

  15. cmdLine.StringVar(&StudentName,

  16. "name", "Default Name",

  17. "This is student depart \ndescription.")

  18. }

  19.  
  20. func main() {

  21. flag.CommandLine = flag.NewFlagSet("", flag.PanicOnError)

  22. flag.CommandLine.Usage = func() {

  23. fmt.Fprintf(os.Stderr, "Usage of %s:\n", "question")

  24. flag.PrintDefaults()

  25. }

  26. cmdLine.Parse(os.Args[1:]) // 接受的参数

  27. fmt.Printf("Hello, %s!\n", StudentName)

  28. }

在demo3-3例子中,完全脱离了flag.CommandLine变量,也就是说无论如何都不会影响到该变量,这样就更灵活了。

  • 4.问题

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

答:string,bool,int三种类型

2.我们可以把自定义的数据类型作为参数值的类型吗?如果可以,怎样做?

答:使用func Set(myset,value string) error 等定义一个类型,var myflag myset定义变量,flag.Var(&myflag, ‘default value’, ‘doc’)

猜你喜欢

转载自blog.csdn.net/sinat_32023305/article/details/81779924
今日推荐