目录
Please enable Javascript to view the contents

Go-fmt格式化IO

 ·  ☕ 2 分钟

重要

fmt 是 Go 中使用频率最高的包之一。日常开发中,三个动词覆盖 90% 场景:%v(默认格式)、%+v(带字段名)、%#v(Go 语法表示)。

环境说明

  • Go:go1.20

1. 输出函数速查

函数输出位置用途
fmt.Printos.Stdout直接打印,无换行
fmt.Printlnos.Stdout打印 + 空格分隔 + 换行
fmt.Printfos.Stdout格式化打印
fmt.Sprintf返回 string格式化返回字符串,不输出
fmt.Fprintfio.Writer格式化写入任意 Writer
fmt.Errorf返回 errorerrors.New + Sprintf,创建格式化错误

2. 通用动词(最常用)

动词效果示例
%v默认格式fmt.Printf("%v", user){Alice 30}
%+v带字段名fmt.Printf("%+v", user){Name:Alice Age:30}
%#vGo 语法表示fmt.Printf("%#v", user)main.User{Name:"Alice", Age:30}
%T类型fmt.Printf("%T", user)main.User
%%百分号本身fmt.Printf("100%%")100%
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
type User struct {
    Name string
    Age  int
}

u := User{Name: "Alice", Age: 30}

fmt.Printf("%v\n", u)   // {Alice 30}
fmt.Printf("%+v\n", u)  // {Name:Alice Age:30}
fmt.Printf("%#v\n", u)  // main.User{Name:"Alice", Age:30}
fmt.Printf("%T\n", u)   // main.User

日常调试优先用 %+v——看字段名比猜字段位置快得多。

3. 基本类型动词

类型动词说明
bool%ttrue / false
int%d十进制
int%b二进制
int%o八进制
int%x / %X十六进制(小写/大写)
float64%f浮点数(%.2f 两位小数)
float64%e科学计数法
string%s字符串
string%q带引号的字符串(显示转义字符)
[]byte%sbyte 切片按字符串打印
指针%p地址
1
2
3
4
5
6
7
n := 255
fmt.Printf("dec=%d bin=%b hex=%x\n", n, n, n)  // dec=255 bin=11111111 hex=ff

s := "hello\nworld"
fmt.Printf("raw=%s quoted=%q\n", s, s)
// raw=hello        quoted="hello\nworld"
//     world

4. 宽度和精度控制

1
2
3
4
fmt.Printf("|%10s|\n", "hi")     // |        hi|  右对齐,10 字符宽
fmt.Printf("|%-10s|\n", "hi")    // |hi        |  左对齐
fmt.Printf("|%010d|\n", 42)      // |0000000042|   0 填充
fmt.Printf("π ≈ %.3f\n", math.Pi) // π ≈ 3.142      3 位小数

5. 自定义输出:fmt.Stringer

实现 String() string 方法的类型,%v / %s / Println 自动调用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
type User struct {
    Name string
    Age  int
}

func (u User) String() string {
    return fmt.Sprintf("%s (%d years old)", u.Name, u.Age)
}

u := User{Name: "Alice", Age: 30}
fmt.Println(u)  // Alice (30 years old)

实现 String()%+v%#v 仍然会显示struct字段名/Go语法,不会被 String() 覆盖。只有 %v / %s / 无动词的 Println 会用它。

6. 常用场景

6.1 多行字符串

1
2
3
s := fmt.Sprintf(`User: %s
Email: %s
Role: %s`, name, email, role)

6.2 错误包装

1
2
3
if err != nil {
    return fmt.Errorf("get user %s failed: %w", userID, err)
}

%w 是 Go 1.13 引入的错误包装动词,配合 errors.Is / errors.As 使用。

6.3 调试结构体切片

1
2
3
users := []User{{"A", 20}, {"B", 30}}
fmt.Printf("%+v\n", users)
// [{Name:A Age:20} {Name:B Age:30}]

7. 总结

场景推荐
调试打印结构体%+v
打印错误,保留调用链fmt.Errorf("...: %w", err)
日志格式化写入文件fmt.Fprintf(f, ...)
自定义类型可读输出实现 String() string
对齐输出%10s / %-10s

参考链接

分享

Hex
作者
Hex
CloudNative Developer