1、命令行参数包 flag
flag 包就是一个用来解析命令行参数的工具。
1.1、os.Args
import ( "fmt" "os" ) func main() { if len(os.Args) > 0 { for index, arg := range os.Args { fmt.Printf("args[%d]=%v\n", index, arg) } } }
运行结果:
osArgs 的本质是一个字符串切片,它的第一个索引 0 存储的是可执行文件的名称,之后的参数才是用户输入的参数。
1.2、flag 包的基本使用
flag 支持的的命令行参数主要有:数值类型、字符串和时间间隔(time.Duration)等。
- 对于 duration 类型,合法的单位有"ns"、“us” 、“µs”、“ms”、“s”、“m”、“h”。用的时候需要带上单位,比如 1h30m。
1.2.1、命令行参数的定义
命令行参数的定义有两种方式:一种是不带初始值的(flag.Type),一种是带初始值的(flag.TypeVar)。
flag.Type(flag名, 默认值, 帮助信息)
name := flag.String("name", "张三", "姓名") age := flag.Int("age", 18, "年龄") married := flag.Bool("married", false, "婚否") delay := flag.Duration("delay", 0, "时间间隔")
通过查看源码我们可以发现,使用这种方式返回的是一个指针,而不是值:
所以在读取的时候需要使用 * 来取出指针的值。
flag.TypeVar(Type指针, flag名, 默认值, 帮助信息)
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, "时间间隔")
1.2.2、解析命令行参数 flag.Parse()
定义好命令行参数之后,需要显式调用解析命令行参数方法(flag.Parse())才能生效,不然读取不到参数。
flag 支持的命令行参数格式有以下几种:
- -flag xxx (使用空格,一个-符号)
- --flag xxx (使用空格,两个-符号)
- -flag=xxx (使用等号,一个-符号)
- --flag=xxx (使用等号,两个-符号)
对于布尔类型的参数一般用等号来传递,不然解析不到布尔值之后的参数,并且会把布尔值及其之后的参数当做其它参数。
使用 go run ./flag.go 执行或者 go build 编译 go 文件再执行:
go build ./flag.go
1.2.3、其它参数
除了我们定义的参数之外,还可以有其它参数,但是必须跟在我们定义的最后一个参数后面,此外 flag 提供了一些方法来获取其它参数的属性:
//返回命令行参数后的其他参数 fmt.Println(flag.Args()) //返回命令行参数后的其他参数个数 fmt.Println(flag.NArg()) //返回使用的命令行参数个数 fmt.Println(flag.NFlag())
1.3、测试
package main import ( "flag" "fmt" "time" ) func main() { var age int var married bool var delay time.Duration name := flag.String("name", "张三", "姓名") flag.IntVar(&age, "age", 18, "年龄") flag.BoolVar(&married, "married", false, "婚否") flag.DurationVar(&delay, "delay", 0, "延迟的时间间隔") //解析命令行参数 flag.Parse() fmt.Println(*name, age, married, delay) //返回命令行参数后的其他参数 fmt.Println(flag.Args()) //返回命令行参数后的其他参数个数 fmt.Println(flag.NArg()) //返回使用的命令行参数个数 fmt.Println(flag.NFlag()) }
测试1(自定义参数 + 其它参数):
测试2(全为其它参数):
2、时间包 time
Go 语言中使用time.Time类型表示时间。我们可以通过time.Now函数获取当前的时间对象,然后从时间对象中可以获取到年、月、日、时、分、秒等信息。
func main() { now := time.Now() // 2024-05-06 19:44:56.6410767 +0800 CST m=+0.004404001 fmt.Println(now) // 现在是2024年5月6日19时46分38秒 fmt.Printf("现在是%d年%d月%d日%d时%d分%d秒", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second()) }
2.1、Location和time zone
这个还是比较实用的,因为 time.LoadLocation 依赖系统的时区数据库,在不太确定程序运行环境的情况下建议先自定义时区偏移量(比如北京时间就是东八区时间,需要在UTC基础上+8个小时)然后使用time.FixedZone的方式指定时区。
// 时差(单位:s) diffSeconds := int((8 * time.Hour).Seconds()) // float 转 int // 北京时间 beijing := time.FixedZone("Beijing Time", diffSeconds) // 返回 *Location
2.2、Unix Time
Unix Time是自1970年1月1日 00:00:00 UTC 至当前时间经过的总秒数,我们可以通过 time 提供的方法获得当前的 Unix 秒/毫秒数(微秒、纳秒用不上):
func main() { now := time.Now() // 都是返回 int64 类型的整数 timestamp := now.Unix() millisecond := now.UnixMilli() // 1714996867s,1714996867336ms fmt.Printf("%ds,%dms", timestamp, millisecond) }
我们也可以把秒/毫秒数(int64)转为时间:
func main() { now := time.Now() // 都是返回 int64 类型的整数 second := now.Unix() // 第2个参数为不足1秒的纳秒数 timeValue := time.Unix(int64(second), 22) fmt.Println(timeValue) // 2024-05-06 20:01:07.000000022 +0800 CST }
2.3、时间间隔
time 包中定义的时间间隔类型的常量如下:
const ( Nanosecond Duration = 1 Microsecond = 1000 * Nanosecond Millisecond = 1000 * Microsecond Second = 1000 * Millisecond Minute = 60 * Second Hour = 60 * Minute )
用的时候直接用常量 * 单位即可,下面是 time.Duration 常用的一些方法:
func main() { now := time.Now() // 这里 Add 方法的参数为 time.Duration 类型 later := now.Add(3 * time.Hour) // 三个小时以后是: 2024-05-06 23:07:28.3043137 +0800 CST m=+10800.004676401 fmt.Println("三个小时以后是: ", later) // Sub 方法的返回值为 time.Duration 类型 fmt.Println(now.Sub(later)) // -3h0m0s // now 是否在 later 之前 fmt.Println(now.Before(later)) // true // now 是否在 later 之后 fmt.Println(now.After(later)) // false // 加载东京所在的时区 tokyo, _ := time.LoadLocation("Asia/Tokyo") // 加载上海所在的时区 shanghai, _ := time.LoadLocation("Asia/Shanghai") tk := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), now.Nanosecond(), tokyo) sh := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), now.Nanosecond(), shanghai) // 判断两个时间是否相同,会考虑时区的影响 fmt.Println(now.Equal(tk)) // false fmt.Println(now.Equal(sh)) // true }
2.4、时间格式化
注意:Go 语言诞生于2006 年 1 月 2 日下午15 点 4 分 5 秒,它的时间格式化模板用的也正是这个时间!
func main() { now := time.Now() // 格式化模板:2006-01-02 15:04:05.000 fmt.Println(now.Format("2006-01-02 15:04:05")) // 2024-05-06 20:24:57 }
2.5、解析时间字符串
func main() { now := time.Now() // 格式化模板:2006-01-02 15:04:05.000 // 两个参数的长度必须对应上 t1, _ := time.Parse("2006-01-02 15:04:05", now.String()[0:19]) fmt.Println(t1) // 2024-05-06 20:34:59 +0000 UTC }
在解析时,可额外指定时区信息:
func main() { now := time.Now() sh, _ := time.LoadLocation("Asia/Shanghai") // 格式化模板:2006-01-02 15:04:05.000 // 按照指定时区和指定格式解析字符串时间 t1, _ := time.ParseInLocation("2006-01-02 15:04:05", now.String()[0:19], sh) fmt.Println(t1) // 2024-05-06 20:40:24 +0800 CST }
Go 语言基础之常用包【flag、time、strconv、io】(2)https://developer.aliyun.com/article/1534277