并没有真正的特定工具,但您可以通过派生 Debug 特征来非常接近。当您为结构派生 Debug 特征时,它将为您提供所有拥有数据的递归表示,以基本类型(例如 str、u32 等)或遇到自定义 Debug 实现时终止。
比如这里的这个程序:
use rand;
#[derive(Debug)]
enum State {
Good,
Bad,
Ugly(&'static str),
}
#[derive(Debug)]
struct ExampleStruct {
x_factor: Option<f32>,
children: Vec<ExampleStruct>,
state: State,
}
impl ExampleStruct {
fn random(max_depth: usize) -> Self {
use rand::Rng;
let mut rng = rand::thread_rng();
let child_count = match max_depth {
0 => 0,
_ => rng.gen::<usize>() % max_depth,
};
let mut children = Vec::with_capacity(child_count);
for _ in 0..child_count {
children.push(ExampleStruct::random(max_depth - 1));
}
let state = if rng.gen() {
State::Good
} else if rng.gen() {
State::Bad
} else {
State::Ugly("really ugly")
};
Self {
x_factor: Some(rng.gen()),
children,
state,
}
}
}
fn main() {
let foo = ExampleStruct::random(3);
dbg!(foo);
}
打印如下内容:
[src/main.rs:51] foo = ExampleStruct {
x_factor: Some(
0.27388978,
),
children: [
ExampleStruct {
x_factor: Some(
0.5051847,
),
children: [
ExampleStruct {
x_factor: Some(
0.9675246,
),
children: [],
state: Ugly(
"really ugly",
),
},
],
state: Bad,
},
ExampleStruct {
x_factor: Some(
0.70672345,
),
children: [],
state: Ugly(
"really ugly",
),
},
],
state: Bad,
}
请注意,并非所有数据都符合要求:孩子们住在堆上的其他地方。它们不存储在 ExampleStruct 中,它们只是归它所有。
如果您存储对事物的引用,这可能会让人感到困惑,因为 Debug 可能会开始遍历这些引用。调试它们不属于它们并不重要。事实上,State::Ugly 内部的&'static str 就是这种情况。构成字符串的实际字节不属于任何变量,它们是硬编码的并且存在于程序本身中。只要程序运行,它们就会存在。