02-Rust基础语法

Rust语法简洁现代,吸收函数式和面向对象优点。强类型系统,编译期保证安全。

变量和可变性

变量声明

// 不可变变量(默认)
let x = 5;
// x = 6;  // ❌ 错误:不可变

// 可变变量
let mut y = 5;
y = 6;  // ✓ OK

// 类型注解
let z: i32 = 5;

// 模式匹配解构
let (a, b) = (1, 2);
let [first, second] = [10, 20];

常量

// 常量:类型必须注解,命名全大写
const MAX_POINTS: u32 = 100_000;  // 下划线提高可读性
const PI: f64 = 3.14159;

// 常量vs不可变变量
// 1. 常量不能用mut
// 2. 常量必须注解类型
// 3. 常量只能是常量表达式,不能是运行时计算
// 4. 常量可在任意作用域声明,包括全局

遮蔽(Shadowing)

let x = 5;
let x = x + 1;  // 遮蔽,x=6
{
    let x = x * 2;  // 内层遮蔽,x=12
    println!("{}", x);  // 12
}
println!("{}", x);  // 6

// 遮蔽可改变类型
let spaces = "   ";
let spaces = spaces.len();  // ✓ OK,类型从&str变为usize

// mut不能改变类型
let mut spaces = "   ";
// spaces = spaces.len();  // ❌ 错误:类型不匹配

数据类型

标量类型

// 整数
i8, i16, i32, i64, i128, isize  // 有符号
u8, u16, u32, u64, u128, usize  // 无符号

let a: u8 = 255;
let b: i32 = -42;
let c = 98_222;       // 98222
let d = 0xff;         // 255(十六进制)
let e = 0o77;         // 63(八进制)
let f = 0b1111_0000;  // 240(二进制)
let g = b'A';         // 65(字节,仅u8)

// 浮点数
f32, f64  // 默认f64

let x = 2.0;       // f64
let y: f32 = 3.0;  // f32

// 布尔
let t = true;
let f: bool = false;

// 字符(4字节Unicode)
let c = 'z';
let emoji = '😻';
let chinese = '中';

复合类型

// 元组:固定长度,不同类型
let tup: (i32, f64, u8) = (500, 6.4, 1);

let (x, y, z) = tup;  // 解构
let five_hundred = tup.0;  // 索引访问

// 单元类型(空元组)
let unit = ();  // 类型:(),函数无返回值时返回

// 数组:固定长度,相同类型
let a = [1, 2, 3, 4, 5];
let a: [i32; 5] = [1, 2, 3, 4, 5];  // 类型:[i32; 5]
let a = [3; 5];  // [3, 3, 3, 3, 3]

let first = a[0];
let second = a[1];

// 数组越界检查(运行时)
// let element = a[10];  // panic!

函数

函数定义

// 基本函数
fn greet() {
    println!("Hello!");
}

// 参数(必须类型注解)
fn greet(name: &str) {
    println!("Hello, {}!", name);
}

// 多参数
fn add(x: i32, y: i32) -> i32 {
    x + y  // 表达式,无分号
}

// 返回值(必须类型注解)
fn five() -> i32 {
    5  // 隐式返回
}

fn plus_one(x: i32) -> i32 {
    x + 1  // ✓ 表达式
    // x + 1;  // ❌ 语句,返回()
}

// 提前返回
fn check(x: i32) -> i32 {
    if x < 0 {
        return 0;  // 提前返回
    }
    x
}

// 无返回值(返回())
fn print_num(x: i32) {
    println!("{}", x);
}

// 发散函数(永不返回)
fn infinite_loop() -> ! {
    loop {
        println!("forever");
    }
}

fn exit_program() -> ! {
    std::process::exit(0);
}

语句和表达式

// 语句:不返回值
let x = 5;

// 表达式:返回值
5
x + 1
{
    let x = 3;
    x + 1  // 表达式,返回4
}

// if是表达式
let number = if condition { 5 } else { 6 };

// 块是表达式
let y = {
    let x = 3;
    x + 1  // 返回4
};

控制流

if表达式

let number = 6;

if number < 5 {
    println!("条件为真");
} else if number == 5 {
    println!("等于5");
} else {
    println!("条件为假");
}

// if是表达式
let condition = true;
let number = if condition { 5 } else { 6 };

// ❌ 错误:类型必须一致
// let number = if condition { 5 } else { "six" };

loop循环

// 无限循环
loop {
    println!("again!");
}

// 返回值
let result = loop {
    counter += 1;
    if counter == 10 {
        break counter * 2;  // 返回20
    }
};

// 循环标签
'outer: loop {
    loop {
        break 'outer;  // 跳出外层循环
    }
}

while循环

let mut number = 3;

while number != 0 {
    println!("{}!", number);
    number -= 1;
}

println!("LIFTOFF!");

for循环

// 遍历集合
let a = [10, 20, 30, 40, 50];

for element in a {
    println!("{}", element);
}

// 范围
for number in 1..4 {  // 1, 2, 3
    println!("{}", number);
}

for number in 1..=4 {  // 1, 2, 3, 4(包含)
    println!("{}", number);
}

// 倒序
for number in (1..4).rev() {  // 3, 2, 1
    println!("{}", number);
}

// 带索引
for (i, value) in a.iter().enumerate() {
    println!("{}: {}", i, value);
}

结构体

定义和实例化

// 定义
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

// 实例化
let user1 = User {
    email: String::from("user@example.com"),
    username: String::from("user123"),
    active: true,
    sign_in_count: 1,
};

// 访问
println!("{}", user1.email);

// 可变
let mut user1 = User { /* ... */ };
user1.email = String::from("new@example.com");

// 字段初始化简写
fn build_user(email: String, username: String) -> User {
    User {
        email,     // 同名简写
        username,
        active: true,
        sign_in_count: 1,
    }
}

// 结构体更新语法
let user2 = User {
    email: String::from("another@example.com"),
    ..user1  // 其余字段从user1复制(移动所有权)
};

元组结构体

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);

// 访问
println!("{}", black.0);

单元结构体

struct AlwaysEqual;

let subject = AlwaysEqual;

方法

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

impl Rectangle {
    // 方法(&self)
    fn area(&self) -> u32 {
        self.width * self.height
    }
    
    // 可变方法
    fn double(&mut self) {
        self.width *= 2;
        self.height *= 2;
    }
    
    // 获取所有权(少见)
    fn consume(self) -> u32 {
        self.width * self.height
    }
    
    // 关联函数(无self)
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
    
    // 多个参数
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}

// 使用
let rect = Rectangle { width: 30, height: 50 };
println!("面积:{}", rect.area());

let sq = Rectangle::square(10);  // 关联函数用::调用

枚举

定义

// 基本枚举
enum IpAddrKind {
    V4,
    V6,
}

let four = IpAddrKind::V4;
let six = IpAddrKind::V6;

// 带数据的枚举
enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}

let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));

// 复杂枚举
enum Message {
    Quit,                       // 无数据
    Move { x: i32, y: i32 },    // 匿名结构体
    Write(String),              // 单个String
    ChangeColor(i32, i32, i32), // 三个i32
}

// 枚举也可以有方法
impl Message {
    fn call(&self) {
        // ...
    }
}

let m = Message::Write(String::from("hello"));
m.call();

Option枚举

// 标准库定义(无需导入)
enum Option<T> {
    Some(T),
    None,
}

let some_number = Some(5);
let some_string = Some("a string");
let absent_number: Option<i32> = None;

// 必须处理None
// let x: i32 = some_number;  // ❌ 错误:类型不匹配

// 正确处理
if let Some(x) = some_number {
    println!("{}", x);
}

match some_number {
    Some(x) => println!("{}", x),
    None => println!("无值"),
}

match表达式

基本用法

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }  // match是表达式
}

// 绑定值
enum UsState {
    Alabama,
    Alaska,
    // ...
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("州: {:?}", state);
            25
        }
    }
}

匹配Option

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);

通配符和_

let dice_roll = 9;

match dice_roll {
    3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    other => move_player(other),  // 绑定其他值
}

match dice_roll {
    3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    _ => (),  // 忽略其他值
}

if let

简化只匹配一个模式的match。

let config_max = Some(3u8);

// match版本
match config_max {
    Some(max) => println!("最大值: {}", max),
    _ => (),
}

// if let简化版
if let Some(max) = config_max {
    println!("最大值: {}", max);
}

// 带else
if let Some(max) = config_max {
    println!("最大值: {}", max);
} else {
    println!("无值");
}

模式匹配

解构

// 解构结构体
struct Point {
    x: i32,
    y: i32,
}

let p = Point { x: 0, y: 7 };

let Point { x: a, y: b } = p;  // a=0, b=7
let Point { x, y } = p;  // 简写

match p {
    Point { x, y: 0 } => println!("在x轴上: {}", x),
    Point { x: 0, y } => println!("在y轴上: {}", y),
    Point { x, y } => println!("({}, {})", x, y),
}

// 解构枚举
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

match msg {
    Message::Quit => {},
    Message::Move { x, y } => {},
    Message::Write(text) => {},
    Message::ChangeColor(r, g, b) => {},
}

// 解构元组
let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 });

守卫(Guard)

let num = Some(4);

match num {
    Some(x) if x < 5 => println!("小于5: {}", x),
    Some(x) => println!("{}", x),
    None => (),
}

// 多个模式
let x = 4;
let y = false;

match x {
    4 | 5 | 6 if y => println!("yes"),  // (4 | 5 | 6) && y
    _ => println!("no"),
}

@绑定

enum Message {
    Hello { id: i32 },
}

let msg = Message::Hello { id: 5 };

match msg {
    Message::Hello { id: id_variable @ 3..=7 } => {
        println!("ID在范围内: {}", id_variable);
    }
    Message::Hello { id: 10..=12 } => {
        println!("ID在另一范围");
    }
    Message::Hello { id } => {
        println!("其他ID: {}", id);
    }
}

Vector

动态数组。

// 创建
let v: Vec<i32> = Vec::new();
let v = vec![1, 2, 3];  // 宏

// 添加
let mut v = Vec::new();
v.push(5);
v.push(6);
v.push(7);

// 访问
let v = vec![1, 2, 3, 4, 5];

let third = &v[2];  // 索引(可能panic)
let third = v.get(2);  // Option<&T>(安全)

match v.get(2) {
    Some(third) => println!("第三个元素: {}", third),
    None => println!("无此元素"),
}

// 遍历
let v = vec![100, 32, 57];
for i in &v {
    println!("{}", i);
}

// 可变遍历
let mut v = vec![100, 32, 57];
for i in &mut v {
    *i += 50;
}

// 存储不同类型(用枚举)
enum SpreadsheetCell {
    Int(i32),
    Float(f64),
    Text(String),
}

let row = vec![
    SpreadsheetCell::Int(3),
    SpreadsheetCell::Text(String::from("blue")),
    SpreadsheetCell::Float(10.12),
];

String

// 创建
let s = String::new();
let s = "initial contents".to_string();
let s = String::from("initial contents");

// 更新
let mut s = String::from("foo");
s.push_str("bar");  // "foobar"
s.push('!');        // "foobar!"

// 拼接
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2;  // s1被移动,s2仍可用

// format!宏(推荐)
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);  // 不获取所有权

// 索引(❌ 不支持)
let s1 = String::from("hello");
// let h = s1[0];  // 错误

// 切片(小心,可能panic)
let hello = "Здравствуйте";
let s = &hello[0..4];  // "Зд"(每个字母2字节)

// 遍历
for c in "नमस्ते".chars() {
    println!("{}", c);
}

for b in "नमस्ते".bytes() {
    println!("{}", b);
}

HashMap

use std::collections::HashMap;

// 创建
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

// 从Vec创建
let teams = vec![String::from("Blue"), String::from("Yellow")];
let initial_scores = vec![10, 50];
let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();

// 访问
let team_name = String::from("Blue");
let score = scores.get(&team_name);  // Option<&V>

match scores.get(&team_name) {
    Some(score) => println!("{}", score),
    None => println!("无此队伍"),
}

// 遍历
for (key, value) in &scores {
    println!("{}: {}", key, value);
}

// 更新
scores.insert(String::from("Blue"), 25);  // 覆盖

// 仅当不存在时插入
scores.entry(String::from("Blue")).or_insert(50);

// 基于旧值更新
let text = "hello world wonderful world";
let mut map = HashMap::new();

for word in text.split_whitespace() {
    let count = map.entry(word).or_insert(0);
    *count += 1;
}

println!("{:?}", map);  // {"hello": 1, "world": 2, "wonderful": 1}

类型别名

type Kilometers = i32;

let x: i32 = 5;
let y: Kilometers = 5;

// x和y是同一类型

迭代器

基本用法

let v = vec![1, 2, 3, 4, 5];

// for循环自动调用into_iter
for item in v {
    println!("{}", item);  // v被消耗
}

// 三种迭代器
let v = vec![1, 2, 3];

// iter():不可变引用
for item in v.iter() {
    println!("{}", item);  // item是&i32
}

// iter_mut():可变引用
for item in v.iter_mut() {
    *item += 1;
}

// into_iter():获取所有权
for item in v.into_iter() {
    println!("{}", item);  // item是i32,v被消耗
}

迭代器适配器

let v = vec![1, 2, 3, 4, 5];

// map:转换
let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();

// filter:过滤
let evens: Vec<&i32> = v.iter().filter(|x| *x % 2 == 0).collect();

// chain:连接
let v1 = vec![1, 2, 3];
let v2 = vec![4, 5, 6];
let combined: Vec<i32> = v1.iter().chain(v2.iter()).cloned().collect();

// zip:配对
let names = vec!["Alice", "Bob"];
let ages = vec![25, 30];
let pairs: Vec<_> = names.iter().zip(ages.iter()).collect();
// [("Alice", 25), ("Bob", 30)]

// enumerate:带索引
for (i, val) in v.iter().enumerate() {
    println!("{}: {}", i, val);
}

// take:取前N个
let first_three: Vec<&i32> = v.iter().take(3).collect();

// skip:跳过前N个
let skip_two: Vec<&i32> = v.iter().skip(2).collect();

// fold:累积
let sum = v.iter().fold(0, |acc, x| acc + x);

// any/all
let has_even = v.iter().any(|x| x % 2 == 0);
let all_positive = v.iter().all(|x| *x > 0);

// find:查找第一个
let found = v.iter().find(|&&x| x > 3);  // Some(&4)

性能技巧

// ❌ 低效:多次collect
let v = vec![1, 2, 3, 4, 5];
let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();
let filtered: Vec<i32> = doubled.iter().filter(|x| *x > 4).cloned().collect();

// ✅ 高效:链式调用
let result: Vec<i32> = v.iter()
    .map(|x| x * 2)
    .filter(|x| *x > 4)
    .cloned()
    .collect();

// ❌ 低效:重复遍历
let sum: i32 = v.iter().sum();
let count = v.iter().count();

// ✅ 高效:一次遍历
let (sum, count) = v.iter().fold((0, 0), |(sum, count), x| {
    (sum + x, count + 1)
});

闭包

语法和捕获

// 完整语法
let add = |x: i32, y: i32| -> i32 { x + y };

// 类型推断
let add = |x, y| x + y;

// 单表达式
let square = |x| x * x;

// 捕获环境
let factor = 2;
let multiply = |x| x * factor;  // 捕获factor

// 三种捕获方式
let s = String::from("hello");

// 1. 不可变借用(Fn)
let print = || println!("{}", s);
print();
println!("{}", s);  // s仍可用

// 2. 可变借用(FnMut)
let mut s = String::from("hello");
let mut append = || s.push_str(" world");
append();
// println!("{}", s);  // 错误:s被可变借用

// 3. 获取所有权(FnOnce)
let s = String::from("hello");
let consume = move || {
    let _s = s;  // s移入闭包
};
consume();
// consume();  // 错误:FnOnce只能调用一次

闭包作为参数

// 接受闭包
fn apply<F>(f: F, x: i32) -> i32
where
    F: Fn(i32) -> i32,
{
    f(x)
}

let result = apply(|x| x * 2, 5);  // 10

// 返回闭包
fn make_adder(n: i32) -> impl Fn(i32) -> i32 {
    move |x| x + n
}

let add_five = make_adder(5);
println!("{}", add_five(3));  // 8

高级模式匹配

范围匹配

let x = 5;

match x {
    1..=5 => println!("1到5"),
    6..=10 => println!("6到10"),
    _ => println!("其他"),
}

// 字符范围
let c = 'c';
match c {
    'a'..='j' => println!("前10个字母"),
    'k'..='z' => println!("后面的字母"),
    _ => println!("其他"),
}

解构嵌套

enum Color {
    Rgb(u8, u8, u8),
    Hsv(u8, u8, u8),
}

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

let msg = Message::ChangeColor(Color::Rgb(0, 160, 255));

match msg {
    Message::ChangeColor(Color::Rgb(r, g, b)) => {
        println!("RGB({}, {}, {})", r, g, b);
    }
    Message::ChangeColor(Color::Hsv(h, s, v)) => {
        println!("HSV({}, {}, {})", h, s, v);
    }
    Message::Move { x, y } => {
        println!("Move to ({}, {})", x, y);
    }
    _ => {}
}

模式中的引用

let s = Some(String::from("hello"));

// ❌ 所有权移动
match s {
    Some(text) => println!("{}", text),
    None => (),
}
// println!("{:?}", s);  // 错误:s已被move

// ✅ 使用ref
let s = Some(String::from("hello"));
match s {
    Some(ref text) => println!("{}", text),  // text是&String
    None => (),
}
println!("{:?}", s);  // OK

// ✅ 匹配引用
let s = Some(String::from("hello"));
match &s {
    Some(text) => println!("{}", text),  // text是&String
    None => (),
}
println!("{:?}", s);  // OK

多模式和守卫组合

let num = Some(4);

match num {
    Some(x) if x < 5 => println!("小于5: {}", x),
    Some(x @ 1..=5) => println!("1到5: {}", x),
    Some(x @ 10 | x @ 20) => println!("10或20: {}", x),
    Some(x) => println!("其他: {}", x),
    None => (),
}

Ranges

// 范围类型
let r1 = 1..5;        // 1,2,3,4
let r2 = 1..=5;       // 1,2,3,4,5
let r3 = ..5;         // 0,1,2,3,4
let r4 = 1..;         // 1,2,3,...(无限)
let r5 = ..;          // 完整范围

// 范围迭代
for i in 1..5 {
    println!("{}", i);
}

// 范围索引
let s = "hello";
let slice = &s[1..4];  // "ell"

// 范围包含判断
let r = 1..10;
println!("{}", r.contains(&5));  // true

// 范围作为迭代器
let sum: i32 = (1..=100).sum();  // 5050

宏基础

// vec! 宏展开
let v = vec![1, 2, 3];
// 等价于:
let mut temp = Vec::new();
temp.push(1);
temp.push(2);
temp.push(3);
let v = temp;

// println! 是宏
println!("Hello");           // 无参数
println!("x = {}", x);       // 格式化
println!("x = {x}");         // 捕获变量(Rust 2021)
println!("{:?}", v);         // Debug格式
println!("{:#?}", v);        // 漂亮打印

// dbg! 宏(调试)
let x = 5;
dbg!(x);  // 打印:[src/main.rs:2] x = 5

let result = dbg!(x + 1);  // 返回值

核心: Rust语法简洁,类型系统完备,模式匹配功能丰富。所有权是理解其他特性的基础。