GO常用标准库

常用标准库

fmt

fmt包实现了类似C语言printf和scanf的格式化I/O
主要分为向外输出内容和获取输入内容两大部分

格式化占位符

占位符 说明
%v 值的默认格式表示
%+v 类似%v,但输出结构体时会添加字段名
%#v 值的Go语法表示
%T 打印值的类型
%% 百分号
%t true或false
%b 表示为二进制
%c 该值对应的unicode码值
%d 表示为十进制
%o 表示为八进制
%x 表示为十六进制,使用a-f
%X 表示为十六进制,使用A-F
%U 表示为Unicode格式:U+1234,等价于”U+%04X”
%q 该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示
%b 无小数部分、二进制指数的科学计数法,如-123456p-78
%e 科学计数法,如-1234.456e+78
%E 科学计数法,如-1234.456E+78
%f 有小数部分但无指数部分,如123.456
%F 等价于%f
%g 根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)
%G 根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)
%s 直接输出字符串或者[]byte
%q 该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示
%x 每个字节用两字符十六进制数表示(使用a-f
%X 每个字节用两字符十六进制数表示(使用A-F)
%p 表示为十六进制,并加上前导的0x,输出指针
%f 默认宽度,默认精度
%9f 宽度9,默认精度
%.2f 默认宽度,精度2
%9.2f 宽度9,精度2
%9.f 宽度9,精度0
‘+’ 总是输出数值的正负号,对%q(%+q)会生成全部是ASCII字符的输出(通过转义)
‘ ‘ 对数值,正数前加空格而负数前加负号,对字符串采用%x或%X时(% x或% X)会给各打印的字节之间加空格
‘-‘ 在输出右边填充空白而不是默认的左边(即从默认的右对齐切换为左对齐)
‘#’ 八进制数前加0(%#o),十六进制数前加0x(%#x)或0X(%#X),指针去掉前面的0x(%#p)对%q(%#q),对%U(%#U)会输出空格和单引号括起
‘0’ 使用0而不是空格填充,对于数值类型会把填充的0放在正负号后面

输出

Print系列函数会将内容输出到系统的标准输出
Printf函数支持格式化输出字符串
Println函数会在输出内容的结尾添加一个换行符
Fprint系列函数会将内容输出到一个io.Writer接口类型的变量w中,我们通常用这个函数往文件中写入内容
Sprint系列函数会把传入的数据生成并返回一个字符串
Errorf函数根据format参数生成格式化字符串并返回一个包含该字符串的错误

1
2
3
4
5
6
7
8
func main() {
fmt.Print("在终端打印该信息。")
name := "极客小祥"
fmt.Printf("我是:%s\n", name)
fmt.Println("在终端打印单独一行显示")
}
// 在终端打印该信息。我是:极客小祥
// 在终端打印单独一行显示
1
2
3
4
5
6
7
8
9
10
11
12
func main() {
// 向标准输出写入内容
fmt.Fprintln(os.Stdout, "向标准输出写入内容")
fileObj, err := os.OpenFile("./xx.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("打开文件出错,err:", err)
return
}
name := "极客小祥"
// 向打开的文件句柄中写入内容
fmt.Fprintf(fileObj, "往文件中写如信息:%s", name)
}
1
2
3
4
5
6
7
8
func main() {
s1 := fmt.Sprint("极客小祥")
name := "极客小祥"
age := 18
s2 := fmt.Sprintf("name:%s,age:%d", name, age)
s3 := fmt.Sprintln("极客小祥")
fmt.Println(s1, s2, s3)
}
1
2
3
4
5
func main() {
err := fmt.Errorf("这是一个错误")
e := errors.New("原始错误e")
w := fmt.Errorf("Wrap了一个错误%w", e)
}

输入

Go语言fmt包下有fmt.Scanfmt.Scanffmt.Scanln三个函数,可以在程序运行过程中从标准输入获取用户的输入
Scan从标准输入中扫描用户输入的数据,将以空白符分隔的数据分别存入指定的参数
Scanf从标准输入扫描文本,根据format参数指定的格式去读取由空白符分隔的值保存到传递给本函数的参数中
Scanln类似Scan,它在遇到换行时才停止扫描。最后一个数据后面必须有换行或者到达结束位置
bufio.NewReader想完整获取输入的内容,而输入的内容可能包含空格,这种情况下可以使用bufio包来实现
Fscan系列fmt.Scan、fmt.Scanf、fmt.Scanln三个函数,只不过它们不是从标准输入中读取数据而是从io.Reader中读取数据
Sscan系列类似于fmt.Scan、fmt.Scanf、fmt.Scanln三个函数,只不过它们不是从标准输入中读取数据而是从指定字符串中读取数据

1
2
3
4
5
6
7
8
9
10
11
12
func main() {
var (
name string
age int
married bool
)
fmt.Scan(&name, &age, &married)
fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}
// $ ./scan_demo
// 小王子 28 false
// 扫描结果 name:小王子 age:28 married:false
1
2
3
4
5
6
7
8
9
10
11
12
func main() {
var (
name string
age int
married bool
)
fmt.Scanf("1:%s 2:%d 3:%t", &name, &age, &married)
fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}
// $ ./scan_demo
// 1:小王子 2:28 3:false
// 扫描结果 name:小王子 age:28 married:false
1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
var (
name string
age int
married bool
)
// fmt.Scanln遇到回车就结束扫描了
fmt.Scanln(&name, &age, &married)
fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}
// $ ./scan_demo
// 小王子 28 false
// 扫描结果 name:小王子 age:28 married:false
1
2
3
4
5
6
7
func bufioDemo() {
reader := bufio.NewReader(os.Stdin) // 从标准输入生成读对象
fmt.Print("请输入内容:")
text, _ := reader.ReadString('\n') // 读到换行
text = strings.TrimSpace(text)
fmt.Printf("%#v\n", text)
}

time

time 包提供了一些关于时间显示和测量用的函数。time 包中日历的计算采用的是公历
可以通过time.Now函数获取当前的时间对象,然后从时间对象中可以获取到年、月、日、时、分、秒等信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// timeDemo 时间对象的年月日时分秒
func timeDemo() {
now := time.Now() // 获取当前时间
fmt.Printf("current time:%v\n", now)
year := now.Year() // 年
month := now.Month() // 月
day := now.Day() // 日
hour := now.Hour() // 小时
minute := now.Minute() // 分钟
second := now.Second() // 秒
fmt.Println(year, month, day, hour, minute, second)
timestamp := now.Unix() // 秒级时间戳
milli := now.UnixMilli() // 毫秒时间戳 Go1.17+
micro := now.UnixMicro() // 微秒时间戳 Go1.17+
nano := now.UnixNano() // 纳秒时间戳
fmt.Println(timestamp, milli, micro, nano)
}

时间操作

time.Duration是time包定义的一个类型,它代表两个时间点之间经过的时间,以纳秒为单位
time.Duration表示一段时间间隔,可表示的最长时间段大约290年

1
2
3
4
5
6
7
8
9
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)
// time.Duration表示1纳秒,time.Second表示1秒

Add

时间加值

1
2
3
4
5
func main() {
now := time.Now()
later := now.Add(time.Hour) // 当前时间加1小时后的时间
fmt.Println(later)
}

Sub

求两个时间之间的差值

1
2
3
4
5
6
7
8
9
func main() {
now := time.Now()
// 加一天
newDate := now.Add(time.Hour * 24)
// 求差,返回一个Duration对象
sub := newDate.Sub(now)
// 取小时 24
fmt.Println(sub.Hours())
}

Equal

求两个时间是否相等

1
2
3
4
5
6
7
8
func main() {
now := time.Now()
// 加一天
newDate := now.Add(time.Hour * 24)
b := now.Equal(newDate)
// false
fmt.Println(b)
}

Before和After

判断一个时间在另一个时间之前或之后

1
2
3
4
5
6
7
8
func main() {
now := time.Now()
newDate := now.Add(time.Hour * 24) // 加一天
b := newDate.Before(now)
b2 := newDate.After(now)
// false true
fmt.Println(b, b2)
}

时间格式化

time.Format函数能够将一个时间对象格式化输出为指定布局的文本表示形式,
需要注意的是 Go 语言中时间格式化的布局不是常见的Y-m-d H:M:S,而是使用 2006-01-02 15:04:05.000
time.Parse解析字符串格式的时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// formatDemo 时间格式化
func formatDemo() {
now := time.Now()
// 格式化的模板为 2006-01-02 15:04:05

// 24小时制
fmt.Println(now.Format("2006-01-02 15:04:05.000 Mon Jan"))
// 12小时制
fmt.Println(now.Format("2006-01-02 03:04:05.000 PM Mon Jan"))

// 小数点后写0,因为有3个0所以格式化输出的结果也保留3位小数
fmt.Println(now.Format("2006/01/02 15:04:05.000")) // 2022/02/27 00:10:42.960
// 小数点后写9,会省略末尾可能出现的0
fmt.Println(now.Format("2006/01/02 15:04:05.999")) // 2022/02/27 00:10:42.96

// 只格式化时分秒部分
fmt.Println(now.Format("15:04:05"))
// 只格式化日期部分
fmt.Println(now.Format("2006.01.02"))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// parseDemo 指定时区解析时间
func parseDemo() {
// 在没有时区指示符的情况下,time.Parse 返回UTC时间
timeObj, err := time.Parse("2006/01/02 15:04:05", "2022/10/05 11:25:20")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(timeObj) // 2022-10-05 11:25:20 +0000 UTC

// 在有时区指示符的情况下,time.Parse 返回对应时区的时间表示
// RFC3339 = "2006-01-02T15:04:05Z07:00"
timeObj, err = time.Parse(time.RFC3339, "2022-10-05T11:25:20+08:00")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(timeObj) // 2022-10-05 11:25:20 +0800 CST
}

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.Type()和flag.TypeVar()

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

1
2
3
4
5
6
// 返回是对应参数的指针
name := flag.String("name", "张三", "姓名")

var name string
// 需要传入指针类型
flag.StringVar(&name, "name", "张三", "姓名")

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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基础

GO单元测试

GO Model

GO操作Elasticsearch