简洁的分支 (Concise branching)

你对前一个练习的解决方案大概是这样:

impl Ticket {
    pub fn assigned_to(&self) -> &str {
        match &self.status {
            Status::InProgress { assigned_to } => assigned_to,
            Status::Done | Status::ToDo => {
                panic!(
                    "Only `In-Progress` tickets can be \
                    assigned to someone"
                )
            }
        }
    }
}

你只关心 Status::InProgress 这一个变体。 真的有必要把所有其他变体都列出来匹配吗?

新构造来救场!

if let

if let 构造允许你只匹配枚举的一个变体,而无需处理其他所有变体。

下面用 if let 简化 assigned_to 方法:

impl Ticket {
    pub fn assigned_to(&self) -> &str {
        if let Status::InProgress { assigned_to } = &self.status {
            assigned_to
        } else {
            panic!(
                "Only `In-Progress` tickets can be assigned to someone"
            );
        }
    }
}

let/else

如果 else 分支注定要提前返回(panic 也算提前返回!),可以使用 let/else 构造:

impl Ticket {
    pub fn assigned_to(&self) -> &str {
        let Status::InProgress { assigned_to } = &self.status else {
            panic!(
                "Only `In-Progress` tickets can be assigned to someone"
            );
        };
        assigned_to
    }
}

它让你在不引入"右漂移 (right drift)"的情况下完成解构后的赋值,即赋值与前面代码处于同一缩进层级。

风格 (Style)

if letlet/else 都是符合 Rust 习惯用法 (idiomatic) 的构造。
按你认为合适的方式使用它们来提升代码可读性,但别滥用:需要时 match 永远在那儿。

原文链接:英文原文