输出与格式化
本教程共 80 篇 · 第 10 篇 · 更新于 2026-07-27 · 约 8 分钟阅读
10. 输出与格式化
本节目标:掌握 fmt 包的各种输出函数,记住常用的格式化动词,能自由控制输出格式。
fmt 包
fmt 是 Go 标准库里最常用的包之一,负责格式化输入输出。你写的前几个程序几乎都离不开它。
import "fmt"
基本输出函数
fmt.Print
直接输出,不加换行,不加空格:
fmt.Print("Hello")
fmt.Print("World")
// 输出:HelloWorld
相邻的两个参数都不是字符串时,中间会自动加空格:
fmt.Print("a", "b") // 输出:ab
fmt.Print(1, 2, 3) // 输出:1 2 3
fmt.Print("a", 1, true) // 输出:a1 true
fmt.Println
输出后自动加换行符:
fmt.Println("Hello")
fmt.Println("World")
// 输出:
// Hello
// World
多个参数之间自动加空格:
fmt.Println("Name:", "Go", "Year:", 2009)
// 输出:Name: Go Year: 2009
fmt.Printf
按格式化字符串输出,这是最灵活的方式:
fmt.Printf("我叫%s,今年%d岁\n", "小明", 18)
// 输出:我叫小明,今年18岁
三个函数的区别:
| 函数 | 换行 | 格式化 | 用途 |
|---|---|---|---|
Print | 否 | 否 | 简单输出 |
Println | 是 | 否 | 输出一行 |
Printf | 否 | 是 | 格式化输出 |
Tip
Printf不会自动加换行,需要手动写\n。如果你想要格式化 + 自动换行,可以用fmt.Printf加\n,或者先Sprintf再Println。
格式化动词
Printf 用 % 开头的动词(Verb)来控制输出格式。这是从 C 语言继承来的概念。
通用动词
| 动词 | 含义 | 示例 |
|---|---|---|
%v | 默认格式输出 | fmt.Printf("%v", 42) -> 42 |
%+v | 带字段名输出结构体 | fmt.Printf("%+v", user) -> {Name:Go Age:18} |
%#v | Go 语法表示 | fmt.Printf("%#v", "hi") -> "hi" |
%T | 输出类型 | fmt.Printf("%T", 42) -> int |
%% | 输出百分号 | fmt.Printf("100%%") -> 100% |
%v 是万能的,任何类型都能用。不知道用什么的时候就用 %v。
整数
| 动词 | 含义 | 示例 |
|---|---|---|
%d | 十进制 | fmt.Printf("%d", 42) -> 42 |
%b | 二进制 | fmt.Printf("%b", 10) -> 1010 |
%o | 八进制 | fmt.Printf("%o", 8) -> 10 |
%O | 八进制(带 0o 前缀) | fmt.Printf("%O", 8) -> 0o10 |
%x | 十六进制小写 | fmt.Printf("%x", 255) -> ff |
%X | 十六进制大写 | fmt.Printf("%X", 255) -> FF |
%c | 对应 Unicode 字符 | fmt.Printf("%c", 65) -> A |
%q | 带引号的字符 | fmt.Printf("%q", 65) -> 'A' |
浮点数
| 动词 | 含义 | 示例 |
|---|---|---|
%f | 小数 | fmt.Printf("%f", 3.14) -> 3.140000 |
%e | 科学计数法(小写 e) | fmt.Printf("%e", 3.14) -> 3.140000e+00 |
%E | 科学计数法(大写 E) | fmt.Printf("%E", 3.14) -> 3.140000E+00 |
%g | 自动选择 %e 或 %f | fmt.Printf("%g", 3.14) -> 3.14 |
字符串
| 动词 | 含义 | 示例 |
|---|---|---|
%s | 原样输出 | fmt.Printf("%s", "Go") -> Go |
%q | 带双引号 | fmt.Printf("%q", "Go") -> "Go" |
%x | 十六进制字节 | fmt.Printf("%x", "Go") -> 476f |
布尔
| 动词 | 含义 | 示例 |
|---|---|---|
%t | 输出 true 或 false | fmt.Printf("%t", true) -> true |
指针
| 动词 | 含义 | 示例 |
|---|---|---|
%p | 指针地址 | fmt.Printf("%p", &x) -> 0xc0000a2000 |
宽度和精度
在 % 和动词字母之间可以加数字,控制输出的宽度和精度。
宽度
fmt.Printf("|%5d|", 42) // | 42| 右对齐,宽度5
fmt.Printf("|%-5d|", 42) // |42 | 左对齐,宽度5
fmt.Printf("|%05d|", 42) // |00042| 用0填充
精度
对于浮点数,小数点后的数字控制精度:
fmt.Printf("%.2f", 3.14159) // 3.14 保留2位小数
fmt.Printf("%.4f", 3.14159) // 3.1416 保留4位小数
对于字符串,精度控制最大长度:
fmt.Printf("%.3s", "Golang") // Gol 只输出前3个字符
组合使用
fmt.Printf("|%8.2f|", 3.14159) // | 3.14| 宽度8,精度2
Sprintf:格式化但不输出
fmt.Sprintf 和 Printf 用法一样,但它不输出到屏幕,而是返回格式化后的字符串:
msg := fmt.Sprintf("你好,%s!你今年%d岁。", "小明", 18)
fmt.Println(msg)
// 输出:你好,小明!你今年18岁。
这在拼接日志、生成消息等场景非常常用。
Sprint 和 Sprintln
类似地,Sprint 和 Sprintln 返回字符串而不输出:
s1 := fmt.Sprint("a", "b", "c") // "abc"
s2 := fmt.Sprintln("a", "b", "c") // "a b c\n"
Fprintf:输出到指定目标
fmt.Fprintf 可以输出到任何实现了 io.Writer 接口的目标:
fmt.Fprintf(os.Stdout, "输出到标准输出:%d\n", 42)
fmt.Fprintf(os.Stderr, "输出到标准错误:%d\n", 42)
这在写日志或者输出到文件时很有用。
输入函数
fmt.Scan
从标准输入读取,空格分隔:
var name string
var age int
fmt.Scan(&name, &age)
fmt.Printf("你输入了:%s, %d\n", name, age)
输入 Go 18,输出 你输入了:Go, 18。
fmt.Scanf
按格式化字符串读取:
var name string
var age int
fmt.Scanf("%s %d", &name, &age)
fmt.Scanln
读取一行,遇换行结束:
var name string
fmt.Scanln(&name)
Note
fmt.Scan系列在简单的命令行程序里够用了。如果你要做复杂的交互式输入,建议用bufio包的Scanner,处理更灵活。
实际示例
打印表格
func main() {
fmt.Printf("%-10s %5s %5s\n", "名字", "年龄", "分数")
fmt.Printf("%-10s %5d %5.1f\n", "小明", 18, 92.5)
fmt.Printf("%-10s %5d %5.1f\n", "小红", 19, 88.0)
fmt.Printf("%-10s %5d %5.1f\n", "小刚", 20, 95.3)
}
输出:
名字 年龄 分数
小明 18 92.5
小红 19 88.0
小刚 20 95.3
查看类型和值
func main() {
x := 42
s := "hello"
f := 3.14
fmt.Printf("x 的类型:%T,值:%v\n", x, x)
fmt.Printf("s 的类型:%T,值:%v\n", s, s)
fmt.Printf("f 的类型:%T,值:%v\n", f, f)
}
输出:
x 的类型:int,值:42
s 的类型:string,值:hello
f 的类型:float64,值:3.14
Tip调试的时候
%T和%+v是你的好朋友。%T看类型,%+v看结构体内容。
常见问题
Printf 格式不匹配
fmt.Printf("%d", "hello") // 输出:%!d(string=hello)
%d 期望整数,但你给了字符串,Go 会输出一个提示告诉你格式不对。用 go vet 可以检测这类问题。
Println 打印结构体
type User struct {
Name string
Age int
}
u := User{Name: "Go", Age: 18}
fmt.Println(u) // {Go 18}
fmt.Printf("%+v\n", u) // {Name:Go Age:18}
fmt.Printf("%#v\n", u) // main.User{Name:"Go", Age:18}
%+v 带字段名,%#v 带 Go 语法格式,调试时最有用。
学完这节你能做什么
- 用
Print、Println、Printf三种方式输出 - 记住
%v、%d、%s、%f、%T等常用格式化动词 - 控制输出的宽度和精度
- 用
Sprintf拼接格式化字符串 - 用
Scan系列读取用户输入
下一节进入数据类型的学习,从基本类型开始。