rust 1.100的dropguard可在离开作用域时执行闭包,用来回滚一段临时修改。以向vec追加解析结果为例,先记录原长度并建立guard,遇到?提前返回时截断,全部成功后调用dropguard::dismiss保留新增数据。
建立最小可编译示例
use std::mem::DropGuard;
use std::num::ParseIntError;
fn append_numbers(
target: &mut Vec<u32>,
input: &[&str],
) -> Result {
let original_len = target.len();
let mut guard = DropGuard::new(target, move |values| {
values.truncate(original_len);
});
for text in input {
guard.push(text.parse::<u32>()?);
}
DropGuard::dismiss(guard);
Ok(())
}
fn main() {
let mut values = vec![7];
assert!(append_numbers(&mut values, &["8", "bad"]).is_err());
assert_eq!(values, vec![7]);
assert!(append_numbers(&mut values, &["8", "9"]).is_ok());
assert_eq!(values, vec![7, 8, 9]);
}</u32></u32>

DropGuard官方类型说明和示例
为什么提前返回会回滚
Guard持有目标的可变引用,并通过Deref和DerefMut继续访问Vec。解析失败时,?使函数提前返回,Guard随作用域结束而析构,闭包把Vec截回原长度。成功路径必须显式dismiss,否则正常返回同样会执行截断。
把示例保存到使用Rust 1.100工具链的项目中,再用cargo run检查断言;检查失败与成功两条路径是否符合预期。

Rust团队以解析失败回滚说明DropGuard
回滚闭包只覆盖它能实际恢复的状态
此示例只撤销本次追加的Vec元素,不恢复已发送的网络请求、文件写入或其他外部副作用。收尾还依赖析构确实发生;进程被强制终止、采用panic=abort等情况不能据此保证回滚。涉及外部事务时,应使用该系统真实提供的提交和恢复机制。











