go语言学习-标准库flag和log

时间:2021-07-30 01:00:37

Go语言内置的flag包实现了命令行参数的解析,flag包使得开发命令行工具更为简单。

os.Args

获取命令行参数个数

package main

import (
"fmt"
"os"
)

//os.Args
//获取命令行参数

func main() {
//os.Args是一个[]string
if len(os.Args) > 0 {
for index, arg := range os.Args {
fmt.Printf("args[%d]=%v\n", index, arg)
}
}
}

flag包

参数类型

flag包支持的命令行参数类型有bool、int、int64、uint、uint64、float float64、string、duration。

flag参数

有效值

字符串flag

合法字符串

整数flag

1234、0664、0x1234等类型,也可以是负数。

浮点数flag

合法浮点数

bool类型flag

1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False。

时间段flag

任何合法的时间段字符串。如”300ms”、”-1.5h”、”2h45m”。

合法的单位有”ns”、”us” /“µs”、”ms”、”s”、”m”、”h”。

定义命令行flag参数

有以下两种常用的定义命令行flag参数的方法。

flag.Type()

基本格式如下:

flag.Type(flag名, 默认值, 帮助信息)*Type

lag.TypeVar()

基本格式如下: flag.TypeVar(Type指针, flag名, 默认值, 帮助信息) 

flag.Parse()

通过以上两种方法定义好命令行flag参数后,需要通过调用flag.Parse()来对命令行参数进行解析。

支持的命令行参数格式有以下几种:

  • -flag xxx (使用空格,一个-符号)
  • –flag xxx (使用空格,两个-符号)
  • -flag=xxx (使用等号,一个-符号)
  • –flag=xxx (使用等号,两个-符号)

其中,布尔类型的参数必须使用等号的方式指定。

Flag解析在第一个非flag参数(单个”-“不是flag参数)之前停止,或者在终止符”–“之后停止。

其他参数

  • flag.Args() ////返回命令行参数后的其他参数,以[]string类型
  • flag.NArg() //返回命令行参数后的其他参数个数
  • flag.NFlag() //返回使用的命令行参数个数
package main

import (
"flag"
"fmt"
"time"
)

/*
flag.Type()
flag.Type(flag名, 默认值, 帮助信息)*Type例如我们要定义姓名、年龄、婚否三个命令行参数,我们可以按如下方式定义:

name := flag.String("name", "张三", "姓名")
age := flag.Int("age", 18, "年龄")
married := flag.Bool("married", false, "婚否")
delay := flag.Duration("d", 0, "时间间隔")
需要注意的是,此时name、age、married、delay均为对应类型的指针。

flag.TypeVar()
基本格式如下: flag.TypeVar(Type指针, flag名, 默认值, 帮助信息) 例如我们要定义姓名、年龄、婚否三个命令行参数,我们可以按如下方式定义:
*/
func main() {
//定义命令行参数方式1
var name string
var age int
var married bool
var delay time.Duration
flag.StringVar(&name, "name", "张三", "姓名")
flag.IntVar(&age, "age", 18, "年龄")
flag.BoolVar(&married, "married", false, "婚否")
flag.DurationVar(&delay, "d", 0, "延迟的时间间隔")

//解析命令行参数
flag.Parse()
fmt.Println(name, age, married, delay)
//返回命令行参数后的其他参数
fmt.Println(flag.Args())
//返回命令行参数后的其他参数个数
fmt.Println(flag.NArg())
//返回使用的命令行参数个数
fmt.Println(flag.NFlag())
}

运行结果

go语言学习-标准库flag和log


log

log包定义了Logger类型,该类型提供了一些格式化输出的方法。本包也提供了一个预定义的“标准”logger,可以通过调用函数Print系列(Print|Printf|Println)、Fatal系列(Fatal|Fatalf|Fatalln)、和Panic系列(Panic|Panicf|Panicln)来使用,比自行创建一个logger对象更容易使用。

默认日志打印到终端

package main

import (
"log"
)

func main() {
log.Println("这是一条很普通的日志。")
v := "很普通的"
log.Printf("这是一条%s日志。\n", v)
log.Fatalln("这是一条会触发fatal的日志。")
log.Panicln("这是一条会触发panic的日志。")
}

logger会打印每条日志信息的日期、时间,默认输出到系统的标准错误。Fatal系列函数会在写入日志信息后调用os.Exit(1)。Panic系列函数会在写入日志信息后panic。

配置logger

默认情况下的logger只会提供日志的时间信息,但是很多情况下我们希望得到更多信息,比如记录该日志的文件名和行号等。log标准库中为我们提供了定制这些设置的方法。

log标准库中的Flags函数会返回标准logger的输出配置,而SetFlags函数用来设置标准logger的输出配置。

func Flags() int
func SetFlags(flag int)

flag选项

log标准库提供了如下的flag选项,它们是一系列定义好的常量。

const (
// 控制输出日志信息的细节,不能控制输出的顺序和格式。
// 输出的日志在每一项后会有一个冒号分隔:例如2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
Ldate = 1 << iota // 日期:2009/01/23
Ltime // 时间:01:23:23
Lmicroseconds // 微秒级别的时间:01:23:23.123123(用于增强Ltime位)
Llongfile // 文件全路径名+行号: /a/b/c/d.go:23
Lshortfile // 文件名+行号:d.go:23(会覆盖掉Llongfile)
LUTC // 使用UTC时间
LstdFlags = Ldate | Ltime // 标准logger的初始值
)

以下增加log输出选项,配置选项,输出位置

func main() {
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.Println("这是一条很普通的日志。")

//Prefix函数用来查看标准logger的输出前缀,SetPrefix函数用来设置输出前缀。
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.Println("这是一条很普通的日志。")
log.SetPrefix("[pprof]")
//能够在代码中为我们的日志信息添加指定的前缀,方便之后对日志信息进行检索和处理。
log.Println("这是一条很普通的日志。")
}

配置日志输出位置

SetOutput函数用来设置标准logger的输出目的地,默认是标准错误输出。

package main

import (
"fmt"
"log"
"os"
)

func main() {
//创建test.log文件来记录日志
logFile, err := os.OpenFile("./test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("open log file failed, err:", err)
return
}
//定义日志输出
log.SetOutput(logFile)
//设置日志输出选项
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.Println("这是一条很普通的日志。")
//设置日志输出前缀
log.SetPrefix("[小王子]")
log.Println("这是一条很普通的日志。")
}

以下是输出的日志

go语言学习-标准库flag和log

要使用标准的logger,我们通常会把上面的配置操作写到init函数中

func init() {
logFile, err := os.OpenFile("./xx.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("open log file failed, err:", err)
return
}
log.SetOutput(logFile)
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
}

创建logger

log标准库中还提供了一个创建新logger对象的构造函数–New,支持我们创建自己的logger

func main() {
logger := log.New(os.Stdout, "<New>", log.Lshortfile|log.Ldate|log.Ltime)
logger.Println("这是自定义的logger记录的日志。")
}