首页 / Go 语言入门教程 / fmt 包详解

Go 语言入门教程

fmt 包详解

本教程共 80 篇 · 第 72 篇 · 更新于 2026-07-27 · 约 8 分钟阅读

GoGo 入门教程fmt格式化PrintfSscanfPrintScan

72. fmt 包详解

本节目标:掌握 fmt 包的 Print/Scan 系列,背熟常用格式化动词,学会 Sprintf 和 Sscanf 的用法。

三个输出函数,区别在格式:

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}
%#vGo 语法表示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 或 falsetrue
%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

Note

Go 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 包。