Debug 与 Display
想让类型可打印,需要实现 std::fmt 的格式化 trait:std::fmt::Debug 或 std::fmt::Display。
标准库内置类型会自动实现,其他类型需手动实现。
Debug
Debug 很直接:几乎所有类型都能 derive 得到 std::fmt::Debug;Display 则必须手写实现。
实现了 Debug 的类型必须用 {:?} 占位符打印。
#![allow(unused)] fn main() { // 既不能 Display 也不能 Debug struct UnPrintable(i32); // 通过 derive 获取 Debug #[derive(Debug)] struct DebugPrintable(i32); }
- 🌟
/* 填空并修复错误 */ struct Structure(i32); fn main() { // std 里的类型都已实现 fmt::Debug println!("__ months in a year.", 12); println!("Now __ will print!", Structure(3)); }
- 🌟🌟
fmt::Debug让类型可打印,但不够优雅;能否换个占位符(不是{})让输出更美观?
#[derive(Debug)] struct Person { name: String, age: u8 } fn main() { let person = Person { name: "Sunface".to_string(), age: 18 }; /* 让它输出: Person { name: "Sunface", age: 18, } */ println!("{:?}", person); }
- 🌟🌟 也可以手写
Debug实现
#[derive(Debug)] struct Structure(i32); #[derive(Debug)] struct Deep(Structure); fn main() { // derive 没法控制输出格式,如果只想打印一个 `7` 呢? /* 让它输出: Now 7 will print! */ println!("Now {:?} will print!", Deep(Structure(7))); }
Display
Debug 简单易用,但有时我们要自定义展示格式,这时就需要 Display。
Display 不能 derive,只能手写实现;占位符是 {} 而不是 {:?}。
- 🌟🌟
/* 补全实现 */ use std::fmt; struct Point2D { x: f64, y: f64, } impl fmt::Display for Point2D { /* 待实现... */ } impl fmt::Debug for Point2D { /* 待实现... */ } fn main() { let point = Point2D { x: 3.3, y: 7.2 }; assert_eq!(format!("{}",point), "Display: 3.3 + 7.2i"); assert_eq!(format!("{:?}",point), "Debug: Complex { real: 3.3, imag: 7.2 }"); println!("Success!"); }
? 运算符
为包含多个字段的结构体实现 Display 时,每个 write! 都返回 fmt::Result,需要在同一函数里处理。
? 运算符可以帮助我们简化这些错误处理。
- 🌟🌟
/* 让它运行 */ use std::fmt; struct List(Vec<i32>); impl fmt::Display for List { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // 取出内部的 vec let vec = &self.0; write!(f, "[")?; // 枚举迭代,得到索引 count 与值 v for (count, v) in vec.iter().enumerate() { // 不是第一个元素就加逗号 if count != 0 { write!(f, ", ")?; } write!(f, "{}", v)?; } // 收尾 write!(f, "]") } } fn main() { let v = List(vec![1, 2, 3]); assert_eq!(format!("{}",v), "[0: 1, 1: 2, 2: 3]"); println!("Success!"); }
参考答案:https://github.com/sunface/rust-by-practice/blob/master/solutions/formatted-output/debug-display.md(solutions 路径),仅在需要时查看。