楼层: 首页/ 软件技术/ Rust 语言基础/ 基础语法:变量、类型、函数、控制流
03

基础语法:变量、类型、函数、控制流

Variables · Types · Functions · Control Flow

Rust 语法 80% 跟你写过的 Java/C 像,剩下 20% 的差异才是重点——默认不可变、表达式导向、match 穷尽匹配。这一章快速过一遍,盯着跟 Java 不一样的地方看。

变量与可变性:let 默认只读

论为什么默认不可变

Java 里 int count = 0; 随便改,编译器不管。Rust 反过来:let x = 5; 默认只读,想改必须显式写 let mut x = 5;。这逼你写代码时就想清楚"这变量会不会变",从根上减少意外修改的 bug。

fn main() { let x = 5; // 默认不可变 // x = 6; // 编译报错:cannot assign twice to immutable variable let mut y = 5; // mut 才允许改 y = 6; // const 是编译期常量,必须标类型,不能用 mut const MAX_POINTS: u32 = 100_000; // shadowing 变量遮蔽:重新 let 一个同名变量,类型还能变 let spaces = " "; let spaces = spaces.len(); // 从字符串"遮"成数字,合法 println!("{} {} {}", x, y, spaces); }
$ cargo run 5 6 3

数据类型:标量与复合

标量类型一览(Rust 没有默认整数,全得写清楚)
类别类型与说明
有符号整数i8 i16 i32 i64 i128 isize(指针宽度,跟随机器位)
无符号整数u8 u16 u32 u64 u128 usize(最常用 i32 / u64)
浮点f32 f64,默认 f64(跟 Double 一样)
布尔bool,值 true / false
字符char,4 字节的 Unicode 标量值,不是单字节 ASCII('中'、'é'、'字' 都合法)
元组(i32, f64, char),固定长度可混合类型,let (a, b, c) = t; 解构
数组[i32; 5],固定长度,栈上分配;变长的用 Vec(第 10 章)
fn main() { let tup: (i32, f64, bool) = (42, 3.14, true); let (a, b, c) = tup; // 解构 println!("{} {} {}", a, tup.0, c); let arr: [i32; 3] = [1, 2, 3]; println!("第一个元素 {},数组长度 {}", arr[0], arr.len()); // 类型推断:大多数情况不用手写类型 let inferred = 100; // 推断成 i32 let big: i64 = 100; // 需要时再标注 // 类型别名:给长类型起外号,不创建新类型 type Age = i32; let _age: Age = 18; println!("{} {}", inferred, big); }

函数:参数必须标类型

// Rust 函数参数必须标注类型,这是它跟 JS/Python 的硬区别 fn add(a: i32, b: i32) -> i32 { a + b // 最后一行没有分号 = 表达式 = 返回值,等价 return a + b; } // 发散函数:! 返回类型表示"永远不返回"(比如直接 panic 或 loop 死循环) fn diverges() -> ! { panic!("我跑不到头"); } fn main() { println!("2 + 3 = {}", add(2, 3)); }

论表达式 vs 语句:Rust 的灵魂细节

语句干一件事但不返回值(结尾带分号);表达式求值并返回一个值(不带分号)。所以块 { } 本身也是表达式,最后一行不带分号就成了块的值——这就是为什么 if、loop 都能直接当右值赋值。

控制流:if 是表达式,match 穷尽

fn main() { // if/else 是表达式,可以直接赋值(所有分支类型要一致) let n = 7; let msg = if n > 5 { "大于五" } else { "小于等于五" }; // loop 可以 break 带回值 let mut count = 0; let result = loop { count += 1; if count == 3 { break count * 10; } // break 后的值就是 loop 的返回值 }; // for in 遍历区间 [0, 5),Rust 没有 while 风格的三段 for for i in 0..3 { print!("{} ", i); } // match 必须穷尽,编译器逼你处理所有情况 let score = 85; let grade = match score { 90..=100 => "A", 70..=89 => "B", 0..=69 => "C", _ => "无效分", // _ 通配符兜底,覆盖剩下的所有 }; println!("\n{} {} {} {}", msg, result, grade, score); }
$ cargo run 0 1 2 大于五 30 B 85
  • 文档注释:/// 给下面的项写文档(支持 Markdown,里面的代码还会被 cargo test 当测试跑);//! 是给整个模块写文档,放文件开头。
  • if let / while let:只关心一种情况时简化 match,if let Some(v) = opt { ... }。