跳轉至

建立 2026-09-19 更新 2026-09-19

結構體與方法

結構體(struct)把多個相關的欄位組成一個自訂型別。搭配 impl 區塊,可以替這個型別加上方法。Rust 沒有 class,structimpl 就是最常見的物件式寫法。

定義與建立

struct User {
    name: String,
    email: String,
    age: u32,
    active: bool,
}

fn main() {
    let mut user = User {
        name: String::from("小明"),
        email: String::from("ming@example.com"),
        age: 30,
        active: true,
    };

    user.age += 1; // 要修改欄位,整個實例必須是 mut
    println!("{} {} {}", user.name, user.email, user.age);
}

Rust 不允許只把單一欄位標為可變,整個實例要嘛可變,要嘛不可變。

欄位簡寫與更新語法

變數名稱與欄位名稱相同時可以簡寫;..other 則能沿用另一個實例的其餘欄位:

struct User {
    name: String,
    email: String,
    active: bool,
}

fn build_user(name: String, email: String) -> User {
    User { name, email, active: true } // 欄位簡寫
}

fn main() {
    let u1 = build_user(String::from("小明"), String::from("a@example.com"));
    let u2 = User {
        email: String::from("b@example.com"),
        ..u1 // 其餘欄位取自 u1
    };
    println!("{} {}", u2.name, u2.email);
}

注意:..u1 會把 u1 裡沒有被 Copy 的欄位(這裡是 name移動過來,之後 u1 就不能整個使用了。

其他形式

struct Color(u8, u8, u8); // tuple struct:欄位沒有名稱
struct Marker;            // unit struct:沒有任何欄位

fn main() {
    let red = Color(255, 0, 0);
    println!("{} {} {}", red.0, red.1, red.2);
    let _m = Marker;
}

用 derive 輸出除錯資訊

想用 {:?} 印出自訂型別,需要加上 #[derive(Debug)],編譯器會自動產生實作。{:#?} 則以較易讀的多行格式輸出:

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p = Point { x: 3, y: 4 };
    println!("{:?}", p);
    println!("{:#?}", p);
}

方法與關聯函式

impl 區塊為型別定義函式。第一個參數是 self 的稱為方法(method),沒有的稱為關聯函式(associated function):

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 關聯函式:用 Rectangle::new(...) 呼叫,常當作建構函式
    fn new(width: u32, height: u32) -> Self {
        Self { width, height }
    }

    // 方法:唯讀借用 self
    fn area(&self) -> u32 {
        self.width * self.height
    }

    // 方法:需要修改時使用 &mut self
    fn scale(&mut self, factor: u32) {
        self.width *= factor;
        self.height *= factor;
    }

    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}

fn main() {
    let mut rect = Rectangle::new(30, 50);
    println!("面積 {}", rect.area());

    rect.scale(2);
    println!("{:?}", rect);

    let small = Rectangle::new(10, 20);
    println!("放得下嗎? {}", rect.can_hold(&small));
}

self 的三種寫法,對應前面學過的所有權規則:

寫法 意義 使用時機
&self 唯讀借用 最常見,只讀取資料
&mut self 可修改借用 需要修改欄位
self 取走所有權 把實例轉換成別的東西,之後不能再用

Selfimpl 目標型別的別名,寫成 Self 比重複型別名稱方便,也更好維護。

推薦影音

結構體

簡述:微軟《Beginner's Series to Rust》第 15 集,介紹 struct 的定義與使用。

結構體與方法語法

簡述:Let's Get Rusty 依照官方書籍第 5 章製作,涵蓋 struct、方法與關聯函式,對應本頁的「方法與關聯函式」。

下一頁:列舉與模式比對