Rust跨线程场景下如何使用Result<T, Box<dyn Error>>便捷错误处理
解决方案
无第三方依赖方案
两个报错的根因分别为:
- 裸
Box<dyn Error>无Send约束,不满足线程安全传递要求 - 仅添加
Send约束后转换失败,是因为标准库的错误类型转换默认要求额外满足'static生命周期约束,绝大多数场景补充该约束即可正常使用
直接修改返回值的错误类型为Box<dyn Error + Send + 'static>即可,同时注意rayon::try_for_each要求闭包返回的Ok类型为(),调整后可运行代码如下:
use rayon::prelude::*; // 1.5.1 use std::error::Error; fn main() -> Result<(), Box<dyn Error + Send + 'static>> { ["1", "2", "three"] .into_par_iter() .try_for_each(|i| -> Result<(), Box<dyn Error + Send + 'static>> { let inner = i.parse::<usize>()?; // 此处编写inner对应的业务逻辑,无需将inner返回给try_for_each Ok(()) })?; Ok(()) }
如果需要兼容更多场景,可以补充Sync约束,也可以定义全局类型别名简化重复编写:
type ThreadSafeResult<T> = Result<T, Box<dyn Error + Send + Sync + 'static>>;
后续所有跨线程场景的返回值直接使用ThreadSafeResult即可,使用体验和普通Box<dyn Error>完全一致。
工业界常用方案(推荐)
如果允许引入第三方依赖,使用anyhow库是最便捷的选择,anyhow::Error原生实现了Send、Sync约束,兼容所有实现了Error trait的错误类型,使用体验和Box<dyn Error>没有区别:
- Cargo.toml添加依赖:
[dependencies] anyhow = "1.0" rayon = "1.5.1"
- 调整后代码:
use rayon::prelude::*; use anyhow::Result; fn main() -> Result<()> { ["1", "2", "three"] .into_par_iter() .try_for_each(|i| -> Result<()> { let inner = i.parse::<usize>()?; // 业务逻辑 Ok(()) })?; Ok(()) }
内容的提问来源于stack exchange,提问作者Migwell
相关产品推荐
相关产品推荐

