Display Trait / Debug Trait
The Display trait defines string conversion for the {} format, and the Debug trait defines it for the {:?} format. Display is used for end-user output, while Debug is used for developer-facing output.
Syntax
use std::fmt;
struct Point {
x: f64,
y: f64,
}
// Implement the Display trait (used with {}).
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
// Manual implementation of the Debug trait (used with {:?}).
impl fmt::Debug for Point {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Point")
.field("x", &self.x)
.field("y", &self.y)
.finish()
}
}
// Using #[derive(Debug)] for automatic implementation is more common.
#[derive(Debug)]
struct Color { r: u8, g: u8, b: u8 }
Format Specifiers
| Format | Description |
|---|---|
| {} | Outputs using the Display trait. |
| {:?} | Outputs debug information using the Debug trait. |
| {:#?} | Outputs pretty-printed debug information using the Debug trait. |
| {:.2} | Displays the value with two decimal places (Display). |
| {:5} | Right-aligns the value in a field of width 5. |
| {:<10} | Left-aligns the value in a field of width 10. |
| {:0>5} | Right-aligns the value in a field of width 5, padded with zeros. |
| {:b} / {:o} / {:x} | Displays the value in binary / octal / hexadecimal. |
| write!(f, ...) | Writes to the fmt::Formatter. |
Sample Code
use std::fmt;
#[derive(Debug)] // Debug is automatically implemented via derive.
struct Matrix {
a: f64, b: f64,
c: f64, d: f64,
}
// Display must be implemented manually.
impl fmt::Display for Matrix {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[ {:.1} {:.1} ]\n[ {:.1} {:.1} ]",
self.a, self.b, self.c, self.d)
}
}
// Implement Display for an error type (a standard pattern).
#[derive(Debug)]
enum AppError {
NotFound(String),
PermissionDenied,
IoError(String),
}
impl fmt::Display for AppError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AppError::NotFound(name) => write!(f, "'{}' not found", name),
AppError::PermissionDenied => write!(f, "permission denied"),
AppError::IoError(msg) => write!(f, "I/O error: {}", msg),
}
}
}
fn main() {
let m = Matrix { a: 1.0, b: 2.0, c: 3.0, d: 4.0 };
// Display using {}.
println!("Display:\n{}", m);
// Debug output using {:?}.
println!("Debug: {:?}", m);
// Pretty-printed debug output using {:#?}.
println!("Pretty Debug:\n{:#?}", m);
// Examples of format specifiers.
let pi = std::f64::consts::PI;
println!("2 decimal places: {:.2}", pi);
println!("Width 8: {:8.2}", pi);
println!("Left-aligned: {:<8.2}", pi);
println!("Zero-padded (5 digits): {:05}", 42);
println!("Binary: {:b}", 42);
println!("Hexadecimal: {:x}", 255);
println!("Uppercase hex: {:X}", 255);
// Display error values.
let errors = vec![
AppError::NotFound(String::from("config.toml")),
AppError::PermissionDenied,
AppError::IoError(String::from("disk is full")),
];
for e in &errors {
println!("Error: {}", e); // Display
println!("Debug: {:?}", e); // Debug
}
}
Notes
Implementing the Display trait automatically provides the ToString trait as well, making the to_string() method available. It is conventional to implement Display on error types to provide human-readable error messages.
Use Debug during development for inspecting values. Use Display for output shown to end users, and Debug for technical information intended for developers.
For the basics of traits, see trait / impl Trait for Type.
If you find any errors or copyright issues, please contact us.