Skip to content

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.

EXAMPLE: CI-CHECKEDTEST ASSERTED · examples/format-output/src/output_pages.rs#output-write-writeln
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");

The macro works with values that provide write_fmt, typically through one of two traits:

  • std::fmt::Write for Unicode text destinations such as String
  • std::io::Write for 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! 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!.

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!.