go_base_fmt_格式化打印
1.fmt_格式化打印
- fmt 包实现了类似 C 语言 printf 和 scanf 的格式化 I/O
- fmt 包主要分为向外输出内容和获取输入内容两大部分
1.1.print 相关函数
-
Print 系列函数会将内容输出到系统的标准输出,具体输出样式不同
-
Print 函数直接输出内容,
-
Printf 函数支持格式化输出字符串,
-
Println 函数会在输出内容的结尾添加一个换行符
-
语法格式:
func Print(a ...interface{}) (n int, err error)
func Printf(format string, a ...interface{}) (n int, err error)
func Println(a ...interface{}) (n int, err error)
- 实例演示:
package main
import "fmt"
// print 打印
func printDemo() {
fmt.Print("Print 正常打印一行信息
") // Print 函数直接输出内容,默认不换行,支持
换行
a := "你好世界"
fmt.Printf("Printf 格式化打印,%s
", a) // Printf 函数支持格式化输出字符串,默认不换行,支持
换行
fmt.Println("Println 在终端打印单独一行显示") // Println 函数会在输出内容的结尾添加一个换行符
}
func main() {
printDemo()
}
1.2.Fprint 函数
-
Fprint 系列函数会将内容输出到一个 io.Writer 接口类型的变量 w 中,我们通常用这个函数往文件中写入内容
-
语法格式:
func Fprint(w io.Writer, a ...interface{}) (n int, err error)
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
- 实例演示:
// 向标准输出写入内容
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)
- 注意,只要满足 io.Writer 接口的类型都支持写入
1.3.Sprint
-
Sprint 系列函数会把传入的数据生成并返回一个字符串
-
语法格式:
func Sprint(a ...interface{}) string
func Sprintf(format string, a ...interface{}) string
func Sprintln(a ...interface{}) string
- 实例演示:
s1 := fmt.Sprint("沙河小王子")
name := "沙河小王子"
age := 18
s2 := fmt.Sprintf("name:%s,age:%d", name, age)
s3 := fmt.Sprintln("沙河小王子")
fmt.Println(s1, s2, s3)
1.4.Errorf
-
Errorf 函数根据 format 参数生成格式化字符串并返回一个包含该字符串的错误
-
Go1.13 版本为 fmt.Errorf 函数新加了一个 %w 占位符用来生成一个可以包裹 Error 的 Wrapping Error
-
格式语法
func Errorf(format string, a ...interface{}) error
- 实例演示
err := fmt.Errorf("这是一个错误")
e := errors.New("原始错误e")
w := fmt.Errorf("Wrap了一个错误%w", e)
2.格式化占位符
- *printf 系列函数都支持 format 格式化参数,这里按照占位符将被替换的变量类型划分,方便查询和记忆
2.1.通用占位符
占位符 | 说明 |
---|---|
%v | 按照变量值的默认类型打印值 |
%+v | 类似 %v,但输出结构体时会添加字段名 |
%#v | 值的 Go 语法表示 |
%T | 打印值的类型 |
%% | 打印百分号,使用 % 转义 |
2.2.整型占位符
占位符 | 说明 |
---|---|
%d | 表示为十进制 |
%+d | 表示为十进制,带符号的整形 |
%8d | 打印整形,长度为 8 ,右对齐,左边留空(不足的用空格补齐) |
%08d | 打印整形,长度为 8 ,右对齐,不足的使用 0 补齐) |
%-8d | 打印整形,长度为 8 ,左对齐,右边留空(不足的用空格补齐) |
%b | 表示为二进制 |
%c | 该值对应的 unicode 码值 |
%o | 表示为八进制 |
%#o | 表示为八进制,带零的八进制 |
%x | 表示为十六进制,使用 小写 a-f |
%X | 表示为十六进制,使用 大写 A-F |
%#x | 表示为十六进制,带 0x 的十六进制 |
%U | 表示为 Unicode 格式:U+1234,等价于”U+%04X” |
%#U | 打印带字符的 Unicode |
%q | 该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示 |
2.3.浮点数与复数占位符
占位符 | 说明 |
---|---|
%b | 打印浮点数,二进制指数的科学计数法,无小数部分,如-123456p-78 |
%f | 打印浮点数,有小数部分,无指数部分,保留 6 位小数?,如123.456 |
%F | 打印浮点数,有小数部分,无指数部分,保留 6 位小数?,等价于%f |
%e | 打印浮点数,科学计数法显示,如-1234.456e+78 |
%E | 打印浮点数,科学计数法显示,如-1234.456E+78 |
%g | 打印浮点数,根据实际情况采用 %e 或 %f 格式(以获得更简洁、准确的输出) |
%G | 打印浮点数,根据实际情况采用 %e 或 %f 格式(以获得更简洁、准确的输出) |
2.4.布尔型占位符
占位符 | 说明 |
---|---|
%t | true或false |
2.5.字符串和字节 []byte 占位符
占位符 | 说明 |
---|---|
%s | 直接输出 字符串 或者 字节 []byte |
%q | 该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示 |
%x | 每个字节用两字符十六进制数表示(使用a-f) |
%X | 每个字节用两字符十六进制数表示(使用A-F) |
2.6.指针占位符
占位符 | 说明 |
---|---|
%p | 表示为十六进制,加上 0x |
%#p | 表示为十六进制,不含 0x |
2.7.宽度标识符
- 宽度通过一个紧跟在百分号后面的十进制数指定,
- 如果未指定宽度,则表示值时除必需之外不作填充。精度通过(可选的)宽度后跟点号后跟的十进制数指定。
- 如果未指定精度,会使用默认精度;如果点号后没有跟数字,表示精度为 0
位符 | 说明 |
---|---|
%f | 默认宽度,默认精度 |
%9f | 宽度9,默认精度 |
%.2f | 默认宽度,精度2 |
%9.2f | 宽度9,精度2 |
%9.f | 宽度9,精度0 |
2.8.其他占位符-需要结合其他占位符使用
占位符 | 说明 |
---|---|
空格 | 对于数值,正数前加空格而负数前加负号 对于字符串使用 %x 或 %X 时(% x或% X)会给各打印的字节之间加空格 |
零 0 | 使用 0 而不是空格填充,对于数值类型会把填充的 0 放在正负号后 |
加号 + | 总是输出数值的正负号 对 %q(%+q)会生成全部是 ASCII 字符的输出(通过转义) |
减号 - | 在输出内容的右边填充空白而不是默认的左边(即从默认的右对齐切换为左对齐) |
井号 # | 对于在八进制数前加 0(%#o) 对于十六进制数前加 0x(%#x)或 0X(%#X) 对于指针去掉前面的 0x(%#p)对 %q(%#q) 对于 %U(%#U)会输出空格和单引号括起来的 go 字面值 |
- 实例演示
s := "hello世界"
fmt.Printf("%s
", s)
fmt.Printf("%5s
", s)
fmt.Printf("%-5s
", s)
fmt.Printf("%5.7s
", s)
fmt.Printf("%-5.7s
", s)
fmt.Printf("%5.2s
", s)
fmt.Printf("%05s
", s)
// 输出结果
hello世界
hello世界
hello世界
hello世界
hello世界
he
hello世界
2.9.实例演示
package main
import "fmt"
func fmtDemo() {
fmt.Printf("%v
", 100) // 打印默认类型的变量值,100
fmt.Printf("%v
", false) // 打印默认类型的变量值,false
b := "你好""
c := struct{ name string }{"你好""}
fmt.Printf("%v
", c) // 按照该变量的默认类型打印变量值,{你好"}
fmt.Printf("%+v
", c) // 类似 %v,但输出结构体时会添加字段名,{name:你好"}
fmt.Printf("%#v
", c) // 值的 Go 语法表示,struct { name string }{name:"你好""}
fmt.Printf("%T
", b) // 打印变量类型,struct { name string }
fmt.Printf("100%%
") // 打印百分号,100%
}
func intDemo() {
d := 100
fmt.Printf("%d
", d) // 打印整形的十进制 decimal 显示, 100
fmt.Printf("%+d
", d) // 打印整形的十进制 decimal 显示, +100
fmt.Printf("%b
", d) // 打印整形的二进制 Binary 的显示, 1100100
fmt.Printf("%c
", d) // 打印整形对应的 unicode 码值显示, d
fmt.Printf("%o
", d) // 打印整形的八进制 octal 的显示, 144
fmt.Printf("%#o
", d) // 打印整形的八进制带 0 的显示, 0144
fmt.Printf("%x
", d) // 打印整形的十六进制 小写 a-f 的显示, 64
fmt.Printf("%X
", d) // 打印整形的十六进制 大写 A-F 的显示, 64
fmt.Printf("%#X
", d) // 打印整形的十六进制带 0x 的显示, 0X64
fmt.Printf("%U
", d) // 打印整形的 Unicode 格式显示, U+0064
fmt.Printf("%#U
", d) // 打印整形的 Unicode 格式显示,带字符, U+0064 'd'
fmt.Printf("%q
", d) // 打印整形的对应的单引号括起来的 go 语法字符字面值 , 'd'
// 指定长度的 int
fmt.Printf("|%d|
", d) // 打印整形,十进制显示, |100|
fmt.Printf("|%8d|
", d) // 打印整形,长度为 8 ,右对齐,左边留空(不足的用空格补齐), | 100|
fmt.Printf("|%08d|
", d) // 打印整形,长度为 8 ,右对齐,不足的使用 0 补齐), |00000100|
fmt.Printf("|%-8d|
", d) // 打印整形,长度为 8 ,左对齐,右边留空(不足的用空格补齐), |100 |
}
func floatDemo() {
f := 3.14159265487
fmt.Printf("%b
", f) // 打印浮点数,二进制指数的科学计数法,无小数部分, 7074237754911210p-51
fmt.Printf("%f
", f) // 打印浮点数,有小数部分,无指数部分,保留 6 位小数?, 3.141593
fmt.Printf("%F
", f) // 打印浮点数,有小数部分,无指数部分,保留 6 位小数?, 3.141593
fmt.Printf("%e
", f) // 打印浮点数,科学计数法显示, 3.141593e+00
fmt.Printf("%E
", f) // 打印浮点数,科学计数法显示, 3.141593e+00
fmt.Printf("%g
", f) // 打印浮点数,根据实际情况采用 %e 或 %f 格式, 3.14159265487
fmt.Printf("%G
", f) // 打印浮点数,根据实际情况采用 %e 或 %f 格式, 3.14159265487
}
func boolDemo() {
fmt.Printf("%t
", true)
}
func strDemo() {
s := "hello世界"
fmt.Printf("%s
", s) // 直接输出 字符串 或者 字节 []byte
fmt.Printf("%q
", s) // 打印该值对应的双引号括起来的 go 语法字符串字面值
fmt.Printf("%x
", s) // 每个字节用两字符十六进制数表示(使用a-f)
fmt.Printf("%X
", s) // 每个字节用两字符十六进制数表示(使用A-F)
}
func pointerDemo() {
p := 10
fmt.Printf("%p
", &p) // 表示为十六进制,加上 0x, 0xc0000ac058
fmt.Printf("%#p
", &p) // 表示为十六进制,不含 0x, c0000ac058
}
func widthDemo() {
n := 12.34
fmt.Printf("|%f|
", n) // 未指定宽度,使用默认宽度,不足使用 0 补齐, |12.340000|
fmt.Printf("|%9f|
", n) // 宽度 9,默认精度,不足使用 0 补齐, |12.340000|
fmt.Printf("|%.2f|
", n) // 默认宽度,精度 2 两位小数, |12.34|
fmt.Printf("|%9.2f|
", n) // 宽度 9,精度 2,不足使用 0 补齐, | 12.34|
fmt.Printf("|%9.f|
", n) // 宽度 9,精度 0 不足使用 空格 补齐, | 12|
fmt.Printf("|%09.f|
", n) // 宽度 9,精度 0 不足使用 0 补齐, | 12|
}
func otherDemo() {
o := "hello世界"
fmt.Printf("|%s|
", o) // 打印字符串, |hello世界|
fmt.Printf("|%10s|
", o) // 打印字符串,宽度 10,默认右对齐,空格补齐, | hello世界|
fmt.Printf("|%-10s|
", o) // 打印字符串,宽度 10,负号 改为左对齐,空格补齐, |hello世界 |
fmt.Printf("|%2s|
", o) // 打印字符串,宽度 2 少于字符串长度, |hello世界|
fmt.Printf("|%-2s|
", o) // 打印字符串,宽度 2 少于字符串长度, |hello世界|
fmt.Printf("|%10.10s|
", o) // 打印字符串,宽度 10 精度 10 ,与默认相反,右对齐,空格补齐, | hello世界|
fmt.Printf("|%-10.10s|
", o) // 打印字符串,宽度 10 精度 10 ,与默认相反,左对齐,空格补齐, |hello世界 |
fmt.Printf("|%2.2s|
", o) // 打印字符串,宽度 2 精度 2 少于字符串长度,保留 2 个字符,多的截掉, |he|
fmt.Printf("|%-2.2s|
", o) // 打印字符串,宽度 2 精度 2 少于字符串长度,保留 2 个字符,多的截掉, |he|
fmt.Printf("|%010s|
", o) // 打印字符串,宽度 10 ,精度默认,不足使用 0 补齐, |000hello世界|
}
func main() {
fmtDemo()
intDemo()
floatDemo()
boolDemo()
strDemo()
pointerDemo()
widthDemo()
otherDemo()
}
3.获取输入
- Go语言fmt包下有fmt.Scan、fmt.Scanf、fmt.Scanln三个函数,可以在程序运行过程中从标准输入获取用户的输入。
3.1.fmt.Scan
- 用法说明
func Scan(a ...interface{}) (n int, err error)
-
Scan从标准输入扫描文本,读取由空白符分隔的值保存到传递给本函数的参数中,换行符视为空白符
-
本函数返回成功扫描的数据个数和遇到的任何错误。如果读取的数据个数比提供的参数少,会返回一个错误报告原因
-
实例演示
func main() {
var (
name string
age int
married bool
)
fmt.Scan(&name, &age, &married)
fmt.Printf("扫描结果 name:%s age:%d married:%t
", name, age, married)
}
- 将上面的代码编译后在终端执行,在终端依次输入小王子、28和false使用空格分隔。
./scan_demo
小王子 28 false
扫描结果 name:小王子 age:28 married:false
- fmt.Scan 从标准输入中扫描用户输入的数据,将以空白符分隔的数据分别存入指定的参数
3.2.fmt.Scanf
- 用法说明
func Scanf(format string, a ...interface{}) (n int, err error)
- Scanf 从标准输入扫描文本,根据 format 参数指定的格式去读取由空白符分隔的值保存到传递给本函数的参数中
- 本函数返回成功扫描的数据个数和遇到的任何错误
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
", name, age, married)
}
- 将上面的代码编译后在终端执行,在终端按照指定的格式依次输入小王子、28 和 false
./scan_demo
1:小王子 2:28 3:false
扫描结果 name:小王子 age:28 married:false
-
fmt.Scanf 不同于 fmt.Scan 简单的以空格作为输入数据的分隔符,
-
fmt.Scanf 为输入数据指定了具体的输入内容格式,只有按照格式输入数据才会被扫描并存入对应变量
-
例如,我们还是按照上个示例中以空格分隔的方式输入,fmt.Scanf 就不能正确扫描到输入的数据。
./scan_demo
小王子 28 false
扫描结果 name: age:0 married:false
3.3.fmt.Scanln
- 用法说明
func Scanln(a ...interface{}) (n int, err error)
-
Scanln 类似 Scan,它在遇到换行时才停止扫描。最后一个数据后面必须有换行或者到达结束位置。
-
本函数返回成功扫描的数据个数和遇到的任何错误
-
实例演示
func main() {
var (
name string
age int
married bool
)
fmt.Scanln(&name, &age, &married)
fmt.Printf("扫描结果 name:%s age:%d married:%t
", name, age, married)
}
- 将上面的代码编译后在终端执行,在终端依次输入小王子、28 和 false 使用空格分隔。
./scan_demo
小王子 28 false
扫描结果 name:小王子 age:28 married:false
- fmt.Scanln 遇到回车就结束扫描了,这个比较常用。
3.4.bufio.NewReader
- 有时候我们想完整获取输入的内容,而输入的内容可能包含空格,这种情况下可以使用bufio包来实现
- 代码示例
func bufioDemo() {
reader := bufio.NewReader(os.Stdin) // 从标准输入生成读对象
fmt.Print("请输入内容:")
text, _ := reader.ReadString('
') // 读到换行
text = strings.TrimSpace(text)
fmt.Printf("%#v
", text)
}
3.5.Fscan 系列
- 这几个函数功能分别类似于fmt.Scan、fmt.Scanf、fmt.Scanln三个函数,只不过它们不是从标准输入中读取数据而是从io.Reader中读取数据。
- 用法示例
func Fscan(r io.Reader, a ...interface{}) (n int, err error)
func Fscanln(r io.Reader, a ...interface{}) (n int, err error)
func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)
3.6.Sscan 系列
- 这几个函数功能分别类似于 fmt.Scan、fmt.Scanf、fmt.Scanln 三个函数,只不过它们不是从标准输入中读取数据而是从指定字符串中读取数据。
- 用法示例
func Sscan(str string, a ...interface{}) (n int, err error)
func Sscanln(str string, a ...interface{}) (n int, err error)
func Sscanf(str string, format string, a ...interface{}) (n int, err error)
10.参考地址
https://www.liwenzhou.com/posts/Go/go_fmt/