write! and writeln!
write! and writeln! format into a destination you already have. They are the right choice when stdout is not the destination and when creating a separate intermediate String would be unnecessary.
use std::fmt::Write;
let mut output = String::new();
write!(&mut output, "value={}", 42).unwrap();
writeln!(&mut output, ", hex={:#x}", 42).unwrap();
assert_eq!(output, "value=42, hex=0x2a\n");Two writer traits
Section titled “Two writer traits”The macro works with values that provide write_fmt, typically through one of two traits:
std::fmt::Writefor Unicode text destinations such asStringstd::io::Writefor byte-oriented destinations such as files, sockets, and byte buffers
For a String, bring std::fmt::Write into scope. For an I/O writer, bring std::io::Write into scope.
write! vs writeln!
Section titled “write! vs writeln!”write! writes only the formatted content. writeln! also appends a newline.
Both return the result produced by the destination’s write_fmt method. That is commonly fmt::Result for formatting destinations or io::Result for I/O destinations, so application code can propagate a real write failure instead of panicking through print!.
Avoid the intermediate allocation
Section titled “Avoid the intermediate allocation”Writing directly into an existing destination avoids first building a separate String. By contrast, format! creates an owned string and the program still has to write that string somewhere afterward.
format! is useful when you actually need ownership of the finished string; write! is cleaner when the destination already exists.
For the allocation boundary, see format! and format_args!.