打印和格式化
标准输出
控制台打印: 这是最常用的方式,将内容直接显示在屏幕上,适合用户交互、调试信息等.
| 宏 | 换行 | 说明 | 适用场景 |
|---|---|---|---|
print! | ❌ | 输出内容但不换行 | 进度条、提示输入 |
println! | ✅ | 输出内容并自动换行 | 最常用的常规打印 |
dbg! | ✅ | 打印文件名、行号及表达式的值 | 快速调试,会夺取所有权并返回值 |
dbg!(): 是转移,并返回所有权(值),可以在函数最后一行使用,不加分号,相当于即打印又返回值
标准错误
错误信息打印: 当程序出错或需要输出日志(不希望被重定向拦截)时使用.
| 宏 | 换行 | 说明 | 适用场景 |
|---|---|---|---|
eprint! | ❌ | 输出到标准错误流(stderr) | 错误提示前缀 |
eprintln! | ✅ | 输出到标准错误并换行 | 报错、程序异常提示 |
使用
eprintln!即使别人把你的程序结果存入文件,错误信息依然能直接显示在屏幕上
打印占位符
核心特性类 (Traits)
这组最常用,决定了如何"表现"一个变量.
{}: (Display) -- 用于人看的,要求类型实现std::fmt::Display(如数字、字符串).{:?}: (Debug) -- 紧凑输出,用于开发者看的(dbg!默认使用).要求类型实现std::fmt::Debug(大多数结构体用#[derive(Debug)]后可用).{:#?}: (Debug) -- 美化打印.会带缩进和换行,适合查看复杂的结构体.{:p}: (Pointer) -- 指针地址,以十六进制显示内存位置.
- 使用
{var}内联捕获语法时只支持本地变量名,不支持字段访问(如{x.name}无效)- 使用
println!("{}", expr)形式则不受此限制,参数部分可以是任意表达式(如x.name、1 + 2)
数值进制类
用于将整数转换成特定的数制显示.
{:b}: Binary -- 二进制.{:o}: Octal -- 八进制.{:x}/{:X}: Hex -- 十六进制(小写/大写).{:e}/{:E}: Exponential -- 科学计数法(小写/大写).
填充与对齐
用于控制输出内容的宽度和位置(常用于打印表格).
{:5}: 设置最小宽度为 5(默认左对齐).{:>5}: 右对齐,宽度为 5.{:<5}: 左对齐,宽度为 5.{:^5}: 居中对齐,宽度为 5.{:0>5}: 用 0 填充左侧空间(常用于流水号).{:*^5}: 用*填充两侧空间,使其居中.
精度与符号
常用于处理浮点数或特定数值前缀.
{:.2}: 保留 2 位小数.{:+}: 强制显示正负号(例如 +42).{:#x}: 带前缀的十六进制(输出 0x1a 而不是 1a).
rust
let n = 255;
println!("指针: {:p}", &n); // 0x7ffee6b5a5e4
println!("十六进制: {:#x}", n); // 0xff
println!("二进制: {:b}", n); // 11111111
println!("对齐: |{:^10}|", n); // | 255 |println! 系列宏格式规则
- 普通占位符:
println!("Hello, {}!", "world")->Hello, world! - 位置参数:
println!("{1}, {0}", "world", "hello")->hello, world! - 命名参数:
println!("{name} is {age}", name="Alice", age=30)->Alice is 30 - 格式化属性(补零、对齐、精度):
println!("{:03}", 5)->005println!("{:.2}", 3.14159)->3.14
Debug打印:println!("{:?}", vec![1, 2])->[1, 2]
println!、format!、panic!、write!以及debug_assert!等宏,调用的都是 Rust 内部同一个格式化引擎std::fmt,只是它们的参数解析和输出目标不同.
format! 格式化到字符串
这些宏不打印到屏幕,不直接显示,而是将结果"存起来".
| 宏 | 说明 | 返回值 | 适用场景 |
|---|---|---|---|
format! | 格式化内容并返回一个字符串 | String 对象 | 拼接字符串、构造动态文本 |
write! | 将内容写入一个"缓冲区" | Result | 写入文件、写入内存 Buffer |
println!() 和 eprintln!()
这两个宏的底层区别在于它们指向的输出流(Stream)不同.虽然它们都能把文字打在屏幕上,但用途完全不同.
核心区别
特性 println!()eprintln!()全称 Print LineError Print Line输出流 标准输出 (stdout) 标准错误 (stderr) 用途 输出程序的正常业务结果 输出错误信息、调试日志、状态更新 重定向行为 经常被重定向到文件 通常保持留在屏幕上,不被重定向 为什么要分两个?(重定向场景)
在 Linux 或 macOS 终端中,用户经常会把程序的输出保存到文件:
bash$ cargo run > output.txt $ cargo run 2> error.txt #(2> 代表重定向错误流),这时候错误才会进 error.txt- 使用
println!(): 所有内容都会进output.txt.如果程序报错了,错误信息也会进文件,用户在屏幕上什么都看不到,会很困惑. - 使用
eprintln!(): 即使你把正常输出重定向到了文件,eprintln!()的内容依然会显示在屏幕上.这样用户就能立刻看到报错,而不会污染output.txt, 而是进入error.txt.
重定向符号
符号 代表的流 默认行为 适用场景 用法示例 >/1>标准输出 (stdout) 将 println!或正常结果存入文件存储程序运行的数据结果 cargo run > output.txt2>标准错误 (stderr) 将 eprintln!或报错信息存入文件存储程序的报错日志 cargo run 2> error.txt&>全部输出 同时将 stdout 和 stderr 存入同一个文件 完整记录程序运行的所有痕迹 cargo run &> all.txt- 使用
使用建议
println!(): 只用来打印用户请求的数据(比如搜索结果、计算后的数字).eprintln!(): 用来打印"正在执行第 1 步..."、"发生网络错误"或"缺少参数"等非业务数据.
小贴士: 在开发时,如果你习惯用打印大法调试,建议改用
dbg!()宏,它会自动带上文件名和行号,而且它走的是 stderr(和eprintln!()一样),不会干扰你的正常程序输出.
println!() 和 dbg!()
println!宏的设计基于"格式化字符串",它的第一个参数必须是字符串字面量""(格式模板"{}"), 一个萝卜一个坑,参数数量和格式模板中的占位符数量必须匹配,不支持空括号.dbg!宏的设计基于"表达式",它的第一个参数可以是任何表达式、变量或留空(默认打印最后一个表达式的值),参数数量不受限制,支持空括号(会打印当前代码位置).
| 特性 | println! | dbg! |
|---|---|---|
| 第一个参数 | 必须是字符串字面量 "{}" | 可以是任何表达式、变量或留空 |
| 参数数量 | 1 个(纯文本)或多个(带占位符) | 0 个、1 个或多个(多参数视为元组) |
| 是否支持空括号 | 不支持(println!() 仅打印换行) | 支持(dbg!() 打印当前代码位置) |
| 主要用途 | 最终用户输出(定制化格式) | 开发者调试(快速看值和位置) |