Macro std::dbg

1.32.0 · source ·
macro_rules! dbg {
    () => { ... };
    ($val:expr $(,)?) => { ... };
    ($($val:expr),+ $(,)?) => { ... };
}
Expand description

打印并返回给定表达式的值,以进行快速而肮脏的调试。

一个例子:

let a = 2;
let b = dbg!(a * 2) + 1;
// ^-- 打印: [src/main.rs:2] a * 2 = 4
assert_eq!(b, 5);
Run

宏通过使用给定表达式的类型的 Debug 实现将值与宏调用的源位置以及表达式的源代码一起打印到 标准错误 来工作。

调用表达式上的宏会移动并获取它的所有权,然后再返回不变的求值表达式。 如果表达式的类型未实现 Copy,并且您不想放弃所有权,则可以改用 dbg!(&expr) 借用某些表达式 expr

dbg! 宏在发行版中的工作原理完全相同。 当仅在发行版本中发生的调试问题或在发行模式下进行的调试明显更快时,此功能很有用。

请注意,宏的目的是作为调试工具,因此您应该避免在版本控制中长时间使用它 (测试和类似的情况除外)。 使用其他工具 (例如 log crate 的 debug! 宏) 可以更好地完成生产代码的调试输出。

Stability

不应依赖此宏打印的确切输出,并且可能会受到 future 的更改。

Panics

如果写入 io::stderr 失败,就会出现 panics。

进一步的例子

用一种方法:

fn foo(n: usize) {
    if let Some(_) = dbg!(n.checked_sub(4)) {
        // ...
    }
}

foo(3)
Run

打印到 stderr

[src/main.rs:4] n.checked_sub(4) = None

单纯的析因实现:

fn factorial(n: u32) -> u32 {
    if dbg!(n <= 1) {
        dbg!(1)
    } else {
        dbg!(n * factorial(n - 1))
    }
}

dbg!(factorial(4));
Run

打印到 stderr

[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = true
[src/main.rs:4] 1 = 1
[src/main.rs:5] n * factorial(n - 1) = 2
[src/main.rs:5] n * factorial(n - 1) = 6
[src/main.rs:5] n * factorial(n - 1) = 24
[src/main.rs:11] factorial(4) = 24

dbg!(..) 宏移动输入:

/// `usize` 的包装器,重要的是它不可复制。
#[derive(Debug)]
struct NoCopy(usize);

let a = NoCopy(42);
let _ = dbg!(a); // <-- `a` 被移到了这里。
let _ = dbg!(a); // <-- `a` 被再次移动; error!
Run

您也可以使用不带任何值的 dbg!() 来仅在到达文件和行时打印它。

最后,如果要 dbg!(..) 多个值,它将把它们视为一个元组 (并返回它) :

assert_eq!(dbg!(1usize, 2u32), (1, 2));
Run

但是,遵循在宏调用中忽略尾部逗号的约定,带有尾部逗号的单个参数仍不会被视为元组。如果需要一个,可以直接使用一个 1 元组:

assert_eq!(1, dbg!(1u32,)); // 尾部逗号被忽略
assert_eq!((1,), dbg!((1u32,))); // 1-tuple
Run