如何避免在Rust Result调用链中重复调用map_err?
问题分析与解决
错误原因
你尝试的代码报错核心在于**and_then要求链式调用中两次Result的错误类型必须一致**:
peel()返回的是Result<Object, git2::Error>,错误类型为git2::Errorinto_commit()返回的是Result<Commit, Object>,错误类型为git2::Object
两者错误类型不匹配,导致编译器提示类型错误。
正确简化方式
方式一:统一错误类型后链式调用
将into_commit()的错误转换为git2::Error,让两次操作的错误类型对齐,即可正常使用and_then:
use git2::{Error, ErrorClass, ErrorCode}; let mut target_commit = target_object .peel(git2::ObjectType::Commit) .and_then(|obj| { obj.into_commit() // 将Object类型错误转换为git2标准错误类型 .map_err(|_| Error::new(ErrorClass::Object, ErrorCode::InvalidSpec, "无法将对象转换为提交")) }) .map_err(|_| anyhow!("Target `{commitish}` cannot be evaluated as a commit"))?;
方式二:提前包装为anyhow错误
如果不需要保留原始git2::Error细节,也可以直接在链式调用中统一用anyhow包装错误:
let mut target_commit = target_object .peel(git2::ObjectType::Commit) .map_err(|_| anyhow!("Target `{commitish}` cannot be evaluated as a commit")) .and_then(|obj| { obj.into_commit() .map_err(|_| anyhow!("Target `{commitish}` cannot be evaluated as a commit")) })?;
方式三:封装辅助函数(推荐)
如果这类操作会多次使用,封装成辅助函数能让代码更简洁易维护:
use git2::{Object, Commit, Error, ErrorClass, ErrorCode}; /// 将Object转换为Commit,统一错误类型 fn to_commit(obj: Object) -> Result<Commit, Error> { obj.into_commit() .map_err(|_| Error::new(ErrorClass::Object, ErrorCode::InvalidSpec, "对象不是提交类型")) } // 调用示例 let mut target_commit = target_object .peel(git2::ObjectType::Commit) .and_then(to_commit) .map_err(|_| anyhow!("Target `{commitish}` cannot be evaluated as a commit"))?;
内容的提问来源于stack exchange,提问作者larsks
相关产品推荐
相关产品推荐

