无论使用任何编程语言开发应用,都离不开配置数据。配置数据提供的形式有多样,不外乎命令行选项(options)、参数(parameters),环境 变量(env vars)以及配置文件等。Golang也不例外。Golang内置flag标准库,可以用来支持部分命令行选项和参数的解析;Golang通过os包提 供的方法可以获取当前环境变量;但Golang没有规定标准配置文件格式(虽说内置支持xml、json),多通过第三方 包来解决配置文件读取的问题。Golang配置相关的第三方包邮很多,作者在本文中给出的配置方案中就包含了主流的第三方配置数据操作包。
一个良好的应用配置层次应该是这样的:
下面循序渐进探讨golang程序配置方案。
这一节关注golang程序如何访问命令行选项和参数。
golang对访问到命令行参数提供了内建的支持:
//cmdlineargs.go
package main
import (
// "fmt"
"os"
"path/filepath"
)
func main() {
println("I am ", os.Args[0])
baseName := filepath.Base(os.Args[0])
println("The base name is ", baseName)
// The length of array a can be discovered using the built-in function len
println("Argument # is ", len(os.Args))
// the first command line arguments
if len(os.Args) > 1 {
println("The first command line argument: ", os.Args[1])
}
}
执行结果如下:
$go build cmdlineargs.go
$cmdlineargs test one
I am cmdlineargs
The base name is cmdlineargs
Argument # is 3
The first command line argument: test
对于命令行结构复杂一些的程序,我们最起码要用到golang标准库内置的flag包:
//cmdlineflag.go
package main
import (
"flag"
"fmt"
"os"
"strconv"
)
var (
// main operation modes
write = flag.Bool("w", false, "write result back instead of stdout\\n\\t\\tDefault: No write back")
// layout control
tabWidth = flag.Int("tabwidth", 8, "tab width\\n\\t\\tDefault: Standard")
// debugging
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file\\n\\t\\tDefault: no default")
)
func usage() {
// Fprintf allows us to print to a specifed file handle or stream
fmt.Fprintf(os.Stderr, "\\nUsage: %s [flags] file [path ...]\\n\\n",
"CommandLineFlag") // os.Args[0]
flag.PrintDefaults()
os.Exit(0)
}
func main() {
fmt.Printf("Before parsing the flags\\n")
fmt.Printf("T: %d\\nW: %s\\nC: '%s'\\n",
*tabWidth, strconv.FormatBool(*write), *cpuprofile)
flag.Usage = usage
flag.Parse()
// There is also a mandatory non-flag arguments
if len(flag.Args()) < 1 {
usage()
}
fmt.Printf("Testing the flag package\\n")
fmt.Printf("T: %d\\nW: %s\\nC: '%s'\\n",
*tabWidth, strconv.FormatBool(*write), *cpuprofile)
for index, element := range flag.Args() {
fmt.Printf("I: %d C: '%s'\\n", index, element)
}
}
这个例子中: - 说明了三种类型标志的用法:Int、String和Bool。 - 说明了每个标志的定义都由类型、命令行选项文本、默认值以及含义解释组成。 - 最后说明了如何处理标志选项(flag option)以及非option参数。
不带参数运行:
$cmdlineflag
Before parsing the flags
T: 8
W: false
C: ''
Usage: CommandLineFlag [flags] file [path ...]
-cpuprofile="": write cpu profile to this file
Default: no default
-tabwidth=8: tab width
Default: Standard
-w=false: write result back instead of stdout
Default: No write back
带命令行标志以及参数运行(一个没有flag,一个有两个flag):
$cmdlineflag aa bb
Before parsing the flags
T: 8
W: false
C: ''
Testing the flag package
T: 8
W: false
C: ''
I: 0 C: 'aa'
I: 1 C: 'bb'
$cmdlineflag -tabwidth=2 -w aa
Before parsing the flags
T: 8
W: false
C: ''
Testing the flag package
T: 2
W: true
C: ''
I: 0 C: 'aa'