Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

early return

本集目標

return 關鍵字在函數中途就把值回傳出去,不用等到最後一行。

正文

上一集我們學到:函數最後一行不加分號就是回傳值。但有時候你想在函數中間就回傳——遇到某個條件就提前結束。這時候就要用 return 關鍵字。

基本範例:絕對值

fn abs(x: i32) -> i32 {
    if x >= 0 {
        return x; // 如果 x 是正數或零,直接回傳
    }
    -x            // 走到這裡代表 x 是負數,回傳 -x
}

fn main() {
    println!("abs(5) = {}", abs(5));
    println!("abs(-3) = {}", abs(-3));
    println!("abs(0) = {}", abs(0));
}

注意看:

  • return x; → 用 return 關鍵字,要加分號
  • 最後一行 -x → 不加分號,這是「自然回傳」

return vs 不加分號

兩種回傳方式的比較:

// 方式一:用 return(通常用在「提前離開」)
fn abs_v1(x: i32) -> i32 {
    if x >= 0 {
        return x;
    }
    -x
}

// 方式二:純粹用表達式(整個 if-else 就是回傳值)
fn abs_v2(x: i32) -> i32 {
    if x >= 0 {
        x
    } else {
        -x
    }
}

fn main() {}

兩種都對!Rust 社群的慣例是:

  • 有「我想要提前離開」的意思時用 return(方式一)
  • 其他時候都用表達式(方式二)

實用場景:提前擋掉不合法的輸入

fn divide(a: f64, b: f64) -> f64 {
    if b == 0.0 {
        println!("錯誤:不能除以零!");
        return 0.0; // 提前離開
    }

    // 這邊可能又做了很多其他事情......

    a / b
}

fn main() {
    println!("{}", divide(10.0, 3.0));
    println!("{}", divide(10.0, 0.0));
}

這種「先檢查、不對就提前走人」的寫法叫做 guard clause(守衛子句),在實務中非常常見。

回傳 () 的 return

如果函數回傳 ()(例如沒有寫 -> 型別),return 後面不用寫值:

fn check_age(age: i32) {
    if age < 0 {
        println!("年齡不能是負數!");
        return; // 等同於 return ();
    }
    println!("你的年齡是 {}", age);
}

fn main() {
    check_age(25);
    check_age(-3);
}

return;return (); 的簡寫——因為回傳的是 ()(unit type),省略不寫更簡潔。

不要到處用 return

雖然每個回傳值都寫 return 也能跑,但在 Rust 裡這不是好習慣:

// 不太 Rust 的寫法
fn add_v1(a: i32, b: i32) -> i32 {
    return a + b; // 可以跑,但沒必要
}

// Rust 慣用寫法
fn add_v2(a: i32, b: i32) -> i32 {
    a + b         // 最後一行直接當回傳值
}

fn main() {}

return 留給「提前離開」的場景就好。

重點整理

  • return 值; 可以在函數中途提前回傳(記得加分號)
  • 最後一行不加分號的自然回傳是 Rust 的慣用寫法
  • return 最常用在 guard clause:先檢查條件,不對就提前走人
  • 回傳 () 的函數裡,return;return (); 的簡寫
  • 不要每個回傳值都寫 return,只在需要提前離開時才用