programDesign
8 分钟阅读
rustup命令
rustup update
cargo 命令
编译后不输出warning信息
方案 1:临时全局屏蔽所有警告(一次性运行,最常用)
通过环境变量 RUSTFLAGS 给 rustc 统一传参,所有代码(自身 + 依赖)都生效
| |
方案 2:只屏蔽当前项目代码警告(不影响依赖)
用 cargo rustc 编译再运行,分开两步:
| |
方案 3:永久项目全局关闭(Cargo.toml)
写入项目配置,每次构建自动生效:
drop函数
drop函数是存放在堆中的数据对应的变量才可以调用?还是存放在栈中的数据对应的变量也可以调用?
常量
常量中的数据是否可以存放在堆中?
关联函数
来自: https://kaisery.github.io/trpl-zh-cn/ch02-00-guessing-game-tutorial.html
关联函数是针对某个类型实现的函数.
| |
::new 那一行的 :: 语法表明 new 是 String 类型的一个 关联函数.
::标记
官方标准叫法:路径分隔符(path separator). Rust 官方文档、Rust Reference 统一称
::为 path separator,作用是分割命名空间路径。通俗别名(社区常用)
- 双冒号运算符(最口语,大家日常交流都这么叫)
- 作用域解析运算符(借鉴 C++ 说法,Rust 社区广泛通用)
- 对应 C++
::,功能相似:访问类型 / 模块关联项
- 对应 C++
两种核心使用场景(对应猜数字教程里的代码)
场景 1:访问关联函数 / 关联常量(类型
::函数)1 2String::new(); rand::Rng;String::new:::表示new是关联函数,归属String类型,不是实例方法(实例用.)场景 2:模块 /crate 路径分层分隔
1 2use std::cmp::Ordering; std::io::stdin();std::cmp::Ordering:多层路径,::分割 crate → 模块 → 枚举。
和
.点运算符区分(极易混淆)
| 符号 | 名称 | 用途 |
|---|---|---|
:: | 路径分隔符 / 作用域解析符 | 访问类型 / 模块上的关联函数、常量、子模块 |
. | 点运算符(方法调用符) | 访问实例对象的方法、成员 |
| |
注意
语法层面,
::不是独立二元运算符,属于路径语法的标记,而+/*这种才是标准二元运算符;但日常开发沟通中,大家都会统称它为「双冒号运算符」。
表达式和语句
语句(Statements)是执行一些操作但不返回值的指令。
表达式(Expressions)计算并产生一个值。
分支块 {} 是表达式
Rust 块 {} 本身是表达式:
块最后一行不带分号:该行表达式的值就是整个块的值;
块最后一行带分号:块的值为
();示例 1:分支返回数字
1 2 3 4 5 6let x = if true { 100 // 无分号,块值 = 100 } else { 200 }; // x = 100示例 2:分支末尾加分号,返回单元
1 2 3 4 5 6let x = if true { 100; // 带分号,块值 = () } else { 200; }; // x 的类型是 ()
if表达式
整个 if / else if / else 是单一表达式,它的返回值 = 第一个匹配成功分支块 {} 的最终表达式的值。
- 每个分支
{}块的值 = 块内最后一行无分号表达式; - 所有分支必须返回同一种类型,否则编译报错;
- 如果缺少
else,且存在条件为 false 的路径,类型为()(单元)。
但, if也可以当做语句进行使用: 只需要不把它赋值给变量,表达式求值后的返回值直接丢弃:
| |
底层逻辑:
整个 if-else 先算出一个值(这里是 (),因为 println! 带分号),然后没人接收这个值,直接丢弃,视觉和行为上和 C/C++ 的 if 语句完全一致。
你也可以在末尾显式加分号,效果完全相同(多一条空语句,不影响逻辑):
| |
注意
1 2 3 4 5 6fn main() { let unit = if 2 > 1 { 999 }; println!("{:?}", unit); } 以上代码编译时会报错:
error[E0317]: `if` may be missing an `else` clause --> src\main.rs:2:16 | 2 | let unit = if 2 > 1 { | ________________^ 3 | | 999 | | --- found here 4 | | }; | |_____^ expected integer, found `()` | = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type报错核心原因:缺少
else分支,类型不统一
- 先看代码逻辑
1 2 3let unit = if 2 > 1 { 999 };
条件
2 > 1为true,会执行if块,返回999(类型i32)但 Rust 编译器会考虑所有可能分支:万一条件为
false,代码没有任何返回值路径Rust 规定:不带
else的if表达式整体类型必须是(),但你if分支返回i32,两种类型冲突,直接编译报错
编译器视角拆解
当
if有else:两条路径都有明确返回值,要求两边类型一致当
if没有else:
条件成立:执行块,产生块的值
条件不成立:直接跳过整个
if,表达式求值为单元()→ 这就要求:if分支内部的块求值结果必须也是(),否则两条路径类型不一致该代码中:
true 路径:返回
999(i32)false 路径:返回
()类型i32和()不匹配,编译器拒绝编译。
- 两种修复方案
方案 1:补上
else,让两条分支都是i32(推荐,真正取值)
1 2 3 4 5 6let unit = if 2 > 1 { 999 } else { 0 // else 分支也要返回数字,统一 i32 }; println!("{:?}", unit) // 输出 999方案 2:
if分支末尾加分号,让块返回(),匹配无else的单元类型
1 2 3 4let unit = if 2 > 1 { 999; // 末尾分号,块的值变为 () }; println!("{:?}", unit); // 输出 ()
let if
参见以上注意.
if let
if let 是 Rust 中的一种控制流语法,允许你只匹配一种关心的模式,而忽略其他所有情况。它可以看作 match 的“简化版”,非常适合只处理一个分支的场景。下面从语法、原理、对比、解构、组合条件、链式写法等方面详细展开。
- 基本语法
| |
- 模式:任意可反驳的模式(如
Some(x)、Ok(v)、枚举变体、元组、结构体等)。 - 表达式:返回需要匹配的值。
else分支可选,用于处理匹配失败的情况。
- 与
match的对比
match 要求穷尽所有模式,即使你只关心其中一种:
| |
用 if let 可以大幅简化:
| |
如果还想处理其他情况,可以加上 else:
| |
if let 背后本质就是 match 的语法糖,编译器会将其展开成 match,但代码更短、语义更清晰。
- 常见应用场景
3.1 处理 Option
只关心 Some 里的值:
| |
3.2 处理 Result
只关心成功的值:
| |
3.3 自定义枚举
| |
- 带额外条件的
if let(if let 与&&组合)
你可以在模式匹配成功后,立即用 && 附加一个布尔条件,实现更细粒度的控制:
| |
- 条件会短路求值:只有模式匹配成功,才会检查
&&后的表达式。 - 可以使用多个
&&,但不能直接与||混合(优先级问题)。如果确实需要||,可以写成if (let Some(n) = num && n > 5) || other_condition,但这样代码可读性变差,一般更推荐用match或嵌套if。
- 链式
else if let
类似 else if,可以连续匹配不同模式:
| |
这对于匹配多个枚举变体且每个分支简单时,比 match 更清晰。
- 解构复杂模式
if let 支持所有可反驳的模式解构,包括元组、结构体、枚举内嵌数据等。
| |
- 与
ref/ref mut配合
当你想绑定引用而不获取所有权时,可在模式中使用 ref:
| |
类似地,ref mut 可以获取可变引用。
while let:循环版本
if let 只执行一次,while let 则是循环形式,只要模式匹配就不断执行:
| |
它会一直弹出元素,直到 pop() 返回 None。
- 特别注意:非穷尽性
if let 是非穷尽的,它只关心一种模式,所以编译器不会强制你处理其他分支。当逻辑确实只需要处理一种情况时,这很方便;但如果未来枚举增加新变体,if let 不会在编译时提醒你更新代码,而 match 会。这是需要权衡的地方。
- 总结
- 简洁:用于只关心一种匹配分支,减少样板代码。
- 解构能力强:支持元组、结构体、枚举变体等复杂模式。
- 可与
&&条件组合:进行二次过滤。 - 链式使用:
else if let可连续匹配不同模式。 - 循环支持:
while let实现条件循环。
当你发现 match 中大多数分支都为空或简单处理时,if let 通常就是更合适的选择。
loop表达式
match表达式
break语句
continue语句
while语句
while let
for 语句
for in
所有权规则
- Rust 中的每一个
值都有一个所有者(owner)。 值在任一时刻有且只有一个所有者。- 当
所有者离开作用域,这个值将被丢弃。