Go 语言入门教程
fmt 包详解
本教程共 80 篇 · 第 72 篇 · 更新于 2026-07-27 · 约 8 分钟阅读
GoGo 入门教程fmt格式化PrintfSscanfPrintScan
72. fmt 包详解
本节目标:掌握 fmt 包的 Print/Scan 系列,背熟常用格式化动词,学会 Sprintf 和 Sscanf 的用法。
Print 系列
三个输出函数,区别在格式:
fmt.Print("hello", " ", "world") // 原样输出,不加空格换行
fmt.Println("hello", "world") // 参数间加空格,末尾换行
fmt.Printf("%s %d\n", "hello", 42) // 格式化输出
输出:
hello worldhello world
hello world
hello 42
Sprint 系列
和 Print 用法一样,但返回字符串而不是输出:
s1 := fmt.Sprint("hello", "world") // "helloworld"
s2 := fmt.Sprintln("hello", "world") // "hello world\n"
s3 := fmt.Sprintf("%s-%d", "hello", 42) // "hello-42"
适合把格式化结果存起来再用。
Fprint 系列
写入指定的 io.Writer(文件、网络连接等):
fmt.Fprintf(os.Stdout, "hello %s\n", "world") // 写到标准输出
fmt.Fprintf(file, "log: %d\n", count) // 写到文件
格式化动词全表
§10 介绍过常用格式化动词,这里给出完整版,方便查阅。
通用
| 动词 | 说明 | 示例 |
|---|---|---|
%v | 默认格式 | 42 |
%+v | 带字段名 | {Name:Tom Age:18} |
%#v | Go 语法表示 | main.Person{Name:"Tom", Age:18} |
%T | 类型 | main.Person |
%% | 字面百分号 | % |
整数
| 动词 | 说明 | 示例 |
|---|---|---|
%d | 十进制 | 42 |
%b | 二进制 | 101010 |
%o | 八进制 | 52 |
%O | 八进制(带 0o 前缀) | 0o52 |
%x | 十六进制小写 | 2a |
%X | 十六进制大写 | 2A |
%c | 对应 Unicode 字符 | * |
%q | 单引号字符 | '*' |
浮点数
| 动词 | 说明 | 示例 |
|---|---|---|
%f | 小数 | 3.140000 |
%e | 科学计数(小写 e) | 3.140000e+00 |
%E | 科学计数(大写 E) | 3.140000E+00 |
%g | 紧凑表示 | 3.14 |
%.2f | 保留两位小数 | 3.14 |
字符串和切片
| 动词 | 说明 | 示例 |
|---|---|---|
%s | 字符串 | hello |
%q | 带引号字符串 | "hello" |
%x | 字节序列十六进制 | 68656c6c6f |
布尔和指针
| 动词 | 说明 | 示例 |
|---|---|---|
%t | 输出 true 或 false | true |
%p | 指针地址 | 0xc0000a2000 |
宽度和对齐
| 写法 | 说明 | 示例 |
|---|---|---|
%5d | 宽度 5,右对齐 | 42 |
%-5d | 宽度 5,左对齐 | 42 |
%05d | 宽度 5 补零 | 00042 |
%8.2f | 总宽 8,小数 2 位 | 3.14 |
%+v 和 %#v 的区别
调试时这俩很实用:
type Person struct {
Name string
Age int
}
p := Person{Name: "Tom", Age: 18}
fmt.Printf("%v\n", p) // {Tom 18}
fmt.Printf("%+v\n", p) // {Name:Tom Age:18}
fmt.Printf("%#v\n", p) // main.Person{Name:"Tom", Age:18}
%+v 带字段名,%#v 连类型和包名都带出来,最适合排查问题。
Scan 系列
Scan 从输入读取数据,按格式解析:
var name string
var age int
fmt.Scan(&name, &age) // 空格分隔
fmt.Sscan("Tom 18", &name, &age) // 从字符串读
fmt.Fscan(os.Stdin, &name, &age) // 从 Reader 读
Sscanf 格式化解析
Sscanf 按指定格式从字符串里提取数据:
var name string
var age int
n, err := fmt.Sscanf("name:Tom age:18", "name:%s age:%d", &name, &age)
if err != nil {
fmt.Println("解析失败:", err)
}
fmt.Println(name, age, n) // Tom 18 2
返回成功解析的个数和错误。适合解析固定格式的文本。
错误格式化
fmt.Errorf 创建带格式化的错误:
return fmt.Errorf("用户 %s 不存在,code: %d", name, code)
Go 1.13+ 用 %w 包装错误(前面错误处理章节讲过):
return fmt.Errorf("查询失败: %w", err)
Println 自动加空格
Println 的多个参数之间会自动插空格:
fmt.Println("a", "b", "c") // a b c
fmt.Print("a", "b", "c") // abc
记住这点,别在 Println 里手动加空格变成 a b c。
NoteGo 1.26 优化了
fmt.Errorf("x")这种不带格式化动词的调用,分配更少内存,接近errors.New。但语义上还是建议无格式化时用errors.New。
小结
- Print/Println/Printf:输出到标准输出
- Sprint/Sprintln/Sprintf:返回字符串
- Fprint/Fprintf:写入 io.Writer
%v默认,%+v带字段名,%#v带 Go 语法%d整数,%f浮点,%s字符串,%T类型%.2f控制小数位,%5d控制宽度对齐Sscanf按格式从字符串提取数据
下一节讲 os 和 io 包。