实际上并没有针对此的特定工具,但您可以通过派生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可能开始遍历这些引用。对于Debug来说,它们不拥有并不重要。事实上,这就是State::Ugly中的&'static str的情况。组成字符串的实际字节不属于任何变量,它们被硬编码并驻留在程序本身内。它们将存在于程序运行的整个过程中。