Rust 基础语法

以下是用中文详细讲解 Rust 编程语言的基础语法,涵盖变量、数据类型、控制流、函数、结构体、枚举等核心概念,适合初学者快速入门。内容将简洁明了,配以示例代码,确保易于理解。


1. 变量与常量

Rust 是静态类型语言,变量默认不可变,需使用 mut 关键字声明可变变量。

1.1 变量

  • 不可变变量:使用 let 声明,默认不可变。
  • 可变变量:使用 let mut 声明。
  • 类型推断:Rust 编译器会自动推断变量类型,也可显式指定。

示例

fn main() {
    let x = 42; // 不可变变量,类型推断为 i32
    let mut y: i32 = 100; // 可变变量,显式指定类型
    // x = 43; // 错误:不可变变量不能重新赋值
    y = 200; // 正确:可变变量可以重新赋值
    println!("x = {}, y = {}", x, y);
}

1.2 常量

使用 const 声明,必须显式指定类型,且值在编译时确定。

示例

const MAX_VALUE: i32 = 1000;

fn main() {
    println!("最大值: {}", MAX_VALUE);
}

说明

  • 常量不可变,且不能用 mut
  • 常量通常用于全局固定值。

1.3 遮蔽(Shadowing)

可以在同一作用域内重新声明同名变量,覆盖之前的定义。

示例

fn main() {
    let x = 5;
    let x = x + 1; // 遮蔽,x 现在是 6
    {
        let x = x * 2; // 内部作用域,x 现在是 12
        println!("内部 x: {}", x);
    }
    println!("外部 x: {}", x); // 仍然是 6
}

2. 数据类型

Rust 提供标量类型和复合类型,类型安全由编译器严格检查。

2.1 标量类型

  • 整数i8, i16, i32, i64, i128(有符号),u8, u16, u32, u64, u128(无符号),isize, usize(与系统架构相关)。
  • 浮点数f32, f64
  • 布尔值booltruefalse)。
  • 字符char(Unicode 字符,4 字节)。

示例

fn main() {
    let int: i32 = -42;
    let uint: u32 = 100;
    let float: f64 = 3.14;
    let boolean: bool = true;
    let character: char = '中';
    println!("整数: {}, 无符号整数: {}, 浮点数: {}, 布尔: {}, 字符: {}", int, uint, float, boolean, character);
}

2.2 复合类型

  • 元组(Tuple):固定长度,元素类型可不同。
  • 数组:固定长度,元素类型相同。

示例

fn main() {
    // 元组
    let tup: (i32, f64, char) = (42, 3.14, 'a');
    let (x, y, z) = tup; // 解构
    println!("元组: x = {}, y = {}, z = {}", x, y, z);
    println!("通过索引访问: {}", tup.0); // 访问第一个元素

    // 数组
    let arr: [i32; 3] = [1, 2, 3];
    println!("数组: {:?}", arr); // 使用调试格式输出
    println!("数组第一个元素: {}", arr[0]);
}

说明

  • 元组用 . 索引(如 tup.0)。
  • 数组索引从 0 开始,越界访问会引发编译期或运行时错误。

3. 函数

Rust 函数使用 fn 关键字定义,参数和返回值需显式声明类型。

示例

fn main() {
    greet("Alice"); // 调用函数
    let sum = add(5, 10);
    println!("5 + 10 = {}", sum);
}

fn greet(name: &str) { // 无返回值
    println!("你好, {}!", name);
}

fn add(a: i32, b: i32) -> i32 { // 返回 i32 类型
    a + b // 隐式返回(不加分号)
}

说明

  • 函数参数需指定类型。
  • 返回值类型用 -> 指定。
  • 最后表达式(无分号)作为返回值,return 可用于提前返回。

4. 控制流

Rust 提供分支和循环结构,支持条件判断和迭代。

4.1 条件语句(if)

示例

fn main() {
    let number = 7;
    if number > 5 {
        println!("大于 5");
    } else if number == 5 {
        println!("等于 5");
    } else {
        println!("小于 5");
    }

    // if 作为表达式
    let condition = true;
    let result = if condition { 10 } else { 20 };
    println!("result = {}", result);
}

说明

  • if 条件不需括号,但代码块需用 {}
  • if 可用作表达式,返回值类型必须一致。

4.2 循环

Rust 提供三种循环:loopwhilefor

示例

fn main() {
    // loop(无限循环)
    let mut count = 0;
    loop {
        if count >= 3 {
            break; // 退出循环
        }
        println!("loop: {}", count);
        count += 1;
    }

    // while
    let mut number = 3;
    while number > 0 {
        println!("while: {}", number);
        number -= 1;
    }

    // for 循环遍历
    for i in 0..3 { // 0 到 2
        println!("for: {}", i);
    }
}

输出

loop: 0
loop: 1
loop: 2
while: 3
while: 2
while: 1
for: 0
for: 1
for: 2

说明

  • loop 用于无限循环,需用 break 退出。
  • while 基于条件循环。
  • for 常用于迭代范围(如 0..3)或集合。

5. 所有权与借用

所有权是 Rust 的核心特性,确保内存安全。

5.1 所有权规则

  • 每个值有且仅有一个所有者。
  • 当所有者超出作用域时,值会被销毁(释放内存)。
  • 值可以转移(move)或借用。

示例

fn main() {
    let s1 = String::from("hello"); // s1 拥有字符串
    let s2 = s1; // 所有权转移,s1 失效
    // println!("{}", s1); // 错误:s1 已失效
    println!("{}", s2); // 正确
}

5.2 借用

  • 使用 & 创建引用(借用),不转移所有权。
  • 可变借用用 &mut,但同一作用域内只能有一个可变借用。

示例

fn main() {
    let mut s = String::from("hello");
    let r1 = &s; // 不可变借用
    let r2 = &mut s; // 可变借用
    // println!("{}", r1); // 错误:不可变借用与可变借用不能共存
    r2.push_str(", world");
    println!("{}", r2);
}

说明

  • 借用规则防止数据竞争,编译器严格检查。
  • 不可变借用(&)允许多个,访问只读。
  • 可变借用(&mut)只能有一个,允许修改。

6. 结构体(Struct)

结构体用于定义自定义数据类型。

示例

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

fn main() {
    let mut user = User {
        name: String::from("Alice"),
        age: 25,
        active: true,
    };
    user.age = 26; // 修改字段
    println!("姓名: {}, 年龄: {}, 活跃: {}", user.name, user.age, user.active);

    // 结构体更新语法
    let user2 = User {
        name: String::from("Bob"),
        ..user // 复制 user 的其余字段
    };
    println!("用户2: {}", user2.name);
}

说明

  • 结构体字段通过 . 访问。
  • .. 用于复制结构体部分字段。

7. 枚举(Enum)

枚举用于定义一组相关值。

示例

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
}

fn main() {
    let msg = Message::Write(String::from("hello"));
    match msg {
        Message::Quit => println!("退出"),
        Message::Move { x, y } => println!("移动到 ({}, {})", x, y),
        Message::Write(text) => println!("写入: {}", text),
    }
}

说明

  • 枚举可以包含不同类型的数据。
  • 使用 match 模式匹配处理枚举值。

8. 错误处理

Rust 使用 OptionResult 处理可能失败的操作。

8.1 Option

表示值可能存在或不存在。

示例

fn main() {
    let some_value: Option<i32> = Some(42);
    let none_value: Option<i32> = None;
    match some_value {
        Some(x) => println!("值: {}", x),
        None => println!("无值"),
    }
}

8.2 Result

表示操作可能成功或失败。

示例

use std::fs::File;

fn main() {
    let f = File::open("hello.txt");
    match f {
        Ok(file) => println!("文件打开成功: {:?}", file),
        Err(err) => println!("错误: {}", err),
    }
}

说明

  • Option 用于处理可能为空的值。
  • Result 用于处理可能出错的操作。
  • ? 运算符可简化错误传播。

9. 总结

Rust 基础语法包括:

  • 变量letlet mutconst,支持遮蔽。
  • 数据类型:标量(整数、浮点、布尔、字符)、复合(元组、数组)。
  • 函数:使用 fn,支持隐式返回值。
  • 控制流ifloopwhilefor,支持表达式。
  • 所有权与借用:确保内存安全的核心机制。
  • 结构体和枚举:定义自定义类型,配合 match 使用。
  • 错误处理OptionResult 提供安全处理机制。

通过以上内容,你可以开始编写简单的 Rust 程序。如果需要更深入的讲解(如模块系统、闭包、trait 等)或具体示例,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注