Rust报错match分支类型不兼容:期望NaiveDate,实际得到()
Rust 日期解析match分支类型不匹配问题修复
报错信息
match arms have incompatible types. Expected struct `NaiveDate`, found ()
问题原因
Rust要求match表达式所有分支的返回值类型必须完全一致。
出问题的代码中:
Ok分支返回解析成功的NaiveDate类型值Err分支仅调用eprintln!打印日志,该宏返回值为单元类型()
两个分支类型不匹配,同时解析失败后没有中断流程返回错误,后续构造Post结构体时parsed_date变量也无法获得合法值。
前置自定义错误实现
已完成符合Rust规范的自定义错误定义与转换逻辑:
#[derive(Debug)] pub enum CreatePostError { ReadFileError { path: PathBuf }, MetadataError, ParseError { inner_err: ParseError }, } impl fmt::Display for CreatePostError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::ReadFileError { path } => write!(f, "Error reading file {path:?}"), Self::MetadataError => write!(f, "Some metadata is missing"), Self::ParseError { inner_err } => { write!(f, "Error parsing date: {inner_err}") } } } } impl From<chrono::format::ParseError> for CreatePostError { fn from(e: chrono::format::ParseError) -> Self { CreatePostError::ParseError { inner_err: e } } }
修复方案
方案1:使用?语法传播错误(推荐)
直接替换原有match逻辑即可,?会在解析失败时自动完成错误类型转换并向上返回错误,代码最简洁:
let date = &lines[2][DATE_SEP.len()..]; let parsed_date = NaiveDate::parse_from_str(date, "%Y-%m-%d")?;
方案2:保留错误日志打印逻辑
如果需要在解析失败时先打印错误日志再返回,修改Err分支逻辑,打印后直接返回错误:
let date = &lines[2][DATE_SEP.len()..]; let parsed_date = match NaiveDate::parse_from_str(date, "%Y-%m-%d") { Ok(parsed_date) => parsed_date, Err(e) => { let custom_err = CreatePostError::ParseError { inner_err: e }; eprintln!("Error: {:?}", custom_err); return Err(custom_err); } };
修复后完整函数参考
pub fn create_posts(contents: &Vec<String>) -> Result<Vec<Post>, CreatePostError> { const TITLE_SEP: &str = "Title: "; const DESC_SEP: &str = "Description: "; const DATE_SEP: &str = "Date: "; const TAGS_SEP: &str = "Tags: "; let mut posts: Vec<Post> = Vec::new(); for entry in contents { let lines = entry.lines().collect::<Vec<_>>(); let metadata = lines[0].contains(&TITLE_SEP) && lines[1].contains(&DESC_SEP) && lines[2].contains(&DATE_SEP) && lines[3].contains(&TAGS_SEP); if metadata { let date = &lines[2][DATE_SEP.len()..]; let parsed_date = NaiveDate::parse_from_str(date, "%Y-%m-%d")?; let tags: Vec<String> = lines[3][TAGS_SEP.len()..] .split(", ") .map(|s| s.to_string()) .collect(); let mut article_content = String::new(); for line in &lines[4..] { article_content.push_str(line); article_content.push_str("\n") } let post = Post { title: lines[0][TITLE_SEP.len()..].to_string(), description: lines[1][DESC_SEP.len()..].to_string(), date: parsed_date, tags, content: article_content, }; posts.push(post); } else { return Err(CreatePostError::MetadataError); } } Ok(posts) }
额外注意点
- Rust中
match是表达式,所有分支必须返回相同类型的值,否则无法给变量赋值 - 错误处理分支不要仅打印日志不返回/不中断流程,否则会出现无效值导致后续逻辑异常
- 已经实现对应
From特征的错误类型,可以直接用?自动转换传播,减少样板代码 - Rust函数最后一行返回值不需要加
return和分号,直接写表达式即可
内容的提问来源于stack exchange,提问作者crdpa
相关产品推荐
相关产品推荐

