Output macros and destinations
All macros in the formatting family share the same format-string language. The useful distinction is where the formatted bytes go and whether a newline is appended.
| Macro | Destination | Newline | Return |
|---|---|---|---|
format! |
new String |
no | String |
print! / println! |
stdout | no / yes | () |
eprint! / eprintln! |
stderr | no / yes | () |
write! / writeln! |
fmt::Write or io::Write |
no / yes | fmt::Result or io::Result |
format_args! |
deferred formatting arguments | no | fmt::Arguments |
stdout and stderr
Section titled “stdout and stderr”Use stdout for a program’s primary output. Use stderr for errors and progress that should remain separate from piped data.
println!("result={}", 42);
eprintln!("warning: retrying");print! does not append a newline. Because stdout is frequently line-buffered, call flush() when text must be visible immediately.
use std::io::{self, Write};
print!("Continue? [y/N] ");
io::stdout().flush().unwrap();Lock repeated output
Section titled “Lock repeated output”The standard documentation notes that print! locks stdout on every call. For a hot loop, lock once and write through the handle.
use std::io::{self, Write};
let stdout = io::stdout();
let mut output = stdout.lock();
for value in 0..3 {
writeln!(output, "{value}").unwrap();
}Write without an intermediate String
Section titled “Write without an intermediate String”write! targets either std::fmt::Write for Unicode strings or std::io::Write for byte-oriented output.
use std::fmt::Write;
let mut output = String::new();
write!(&mut output, "{:#06x}", 42).unwrap();
assert_eq!(output, "0x002a");Choose the destination
Section titled “Choose the destination”print!vsprintln!for stdout and newline behavioreprint!andeprintln!for stderrwrite!andwriteln!for an existing writer or bufferformat!when you need an ownedStringformat_args!when an API acceptsfmt::Arguments