





















Rust 控制流 运算符 格式化输出 Pattern Matching 多语言对比
学习重点提示 — 建议先通读全文,再重点回顾标注内容
重点掌握(必须)
- match 模式匹配:Rust 最强大的控制流工具,比 C 族 switch 更强大,可解构、范围匹配、卫表达式
- if 是表达式:Rust 的 if/else 返回值,所有分支必须返回同类型值
- 循环返回值:loop 可以有返回值(break value),for 遍历迭代器
- println! 格式化:占位符 {}(Display)、:?}(Debug)、{name}(命名参数)
次重点(理解即可)
- 运算符优先级与 C 族的差异
- 类型转换 as 与 From/Into trait 的对比
- Rust 与 Python/JS 在格式化输出上的差异
思考记忆提示 — FAQ 是全篇的"临考前速背"模块,建议在通读全文后作为复习使用
Rust 的 if 是表达式(Expression),可以返回值;C 族的 if 是语句(Statement),没有返回值。在 Rust 中,let x = if condition { 1 } else { 2 }; 是合法代码,x 的值是 1 或 2。这要求 if 的所有分支返回相同类型。在 C 中,if 只能控制执行流程,不能作为右值。
match 支持解构(Destructure)、范围匹配(1..=5)、卫表达式(Guard)、通配符(_),且每个分支的值是表达式的结果,可以返回值;switch 仅支持整数/枚举常量比较。例如:match x { Some(n) if n > 0 => ... } 中卫表达式(if n > 0)允许在模式匹配后再加条件过滤,这是 switch 完全做不到的。
因为 Rust 的 if 是表达式,可以直接替代三元运算符的功能,不需要额外的语法。在 C 中需要 int x = a > b ? a : b;,在 Rust 中直接写 let x = if a > b { a } else { b };,语义更清晰,分支可以是多行代码块。三元运算符本质上是"表达式版本的 if",Rust 已经有了更好的方案。
loop 是无限循环,需要手动用 break 退出;while 是条件循环;for 是迭代器循环。关键区别是 loop 可以通过 break value 返回值,而 while/for 不行。loop 是 Rust 最接近"do-while"的概念(至少执行一次),配合标签('label:)可以从深层嵌套循环中直接 break。
Rust 的 for 只能遍历迭代器(Iterator),没有 C 式的 for (i=0; i<n; i++) 三段式语法;Rust 通过 for item in collection 或 for i in 0..n 实现等效功能。这是 Rust 推崇的"迭代器即循环"哲学——迭代器在 Rust 中无处不在(Vec、HashMap、Range 都是迭代器),链式调用 .map().filter().collect() 比三段式 for 循环更表达力强。
是的。Rust 的 match 强制穷举(Exhaustive Matching),编译器会检查是否所有可能都被覆盖;未覆盖的变体会报错,除非使用通配符 _ 或 .. 来捕获其余情况。这个特性保证了每次 match 都是完整的,不会出现 C switch 忘记写 default 导致的安全隐患。Rust 编译器还会提示"缺少哪些变体",是极佳的编码辅助。
支持,但更 Rust 风格的做法是用 break value 从 loop 表达式返回值——return 用于从函数中提前返回,break 用于从循环中跳出。break 返回值让 Rust 的循环成为"表达式",可以赋值给变量:let result = loop { break 42; };(result = 42)。这是 Rust 推崇的"用表达式而非语句"的函数式风格。
Rust 在 Debug 模式下会 panic(在溢出时崩溃),在 Release 模式下使用二进制回绕(wrapping);C/C++ 是未定义行为(UB),编译器可以自由优化,可能产生意想不到的结果。Rust 提供了 .wrapping_add()、.checked_add()、.saturating_add()、.overflowing_add() 四个方法让开发者显式选择溢出处理策略,安全性远高于 C/C++ 的 UB。
行为相同(短路求值),但返回类型不同——Rust 逻辑运算符返回的是布尔值 bool,不是整数(0/1),且 Rust 不允许将布尔值隐式转换为整数。在 C 中,a && b 返回的是 0 或 1(整数),可以用作整数参与算术运算;Rust 的布尔运算是纯布尔代数,不允许隐式混入算术运算,更安全。
大部分相同(&、|、^、<<、>>),但有一个重要区别:Rust 的移位运算符要求右操作数的类型必须是 usize,且移位量必须小于左操作数的位数。在 C 中,移位量超过类型位数是未定义行为(UB);Rust 会在编译期或运行时检查移位量合法性,超出时 panic(Debug)或回绕(Release),不会产生 UB。
Rust 只有 ==,没有 ===。Rust 的 == 比较值的相等性(由 PartialEq trait 定义),不存在 JS 中"值相等但类型不等"的歧义。在 JS 中,== 会做类型强制转换("5" == 5 为 true),=== 不做类型转换。Rust 从设计上拒绝了隐式类型强制转换,所以只需要一个相等比较运算符,消除了 == vs === 的困惑。
as 是编译期已知的安全类型转换(数值类型之间、基本指针转换);From/Into 是 trait,用于实现自定义类型之间的转换,是更通用的抽象。经验法则:数值类型之间用 as(如 i32 as u64),自定义类型或语义化转换用 From/Into(如 String::from("hello"))。as 转换不调用任何运行时代码(零成本),而 From/Into 可能涉及堆分配。
支持,但只能通过 trait 实现,不能自定义运算符符号本身——可以重载哪些运算符由标准库决定。Rust 通过实现 trait 来重载运算符:Add(+)、Sub(-)、Index([])、Deref(*)等。标准库中的 Vec<T> 实现了 Index<usize>,所以可以用 v[0] 访问元素。这与 C++ 的自由运算符重载(可以在任何地方定义 operator+)不同,Rust 限制更严格,更安全。
大部分相同,但 Rust 的优先级表比 C 更简洁——Rust 只有 17 级优先级(不包括路径分隔符),且逻辑运算符(&&)优先级低于比较运算符,这与 C 的 && vs == 关系一致。Rust 的优先级表在官方文档中有明确定义,不像 C 中存在一些"陷阱"(如 C 中 x << y + z 容易被误解)。Rust 社区推荐用括号明确表达优先级,即使在优先级清晰的情况下——这是"显式优于隐式"哲学的体现。
println! 是宏,接受的是格式化参数列表(编译期检查格式字符串的类型安全性),而 printf 是函数,使用 %d/%s 占位符在运行时解析格式(类型不安全)。Rust 的编译器会检查 println! 的参数类型是否与格式占位符匹配——如果传入的字符串给到了 {} 占位符但类型不匹配,编译器会报错(这解决了 C 中 printf("%s", integer) 不会报错但会产生垃圾输出的问题)。
{} 调用 Display trait,用于为用户设计的自定义格式化输出;{:?} 调用 Debug trait,用于调试输出,默认格式为 TypeName { field: value, ... }。所有基本类型(i32、String 等)同时实现了 Display 和 Debug。对于自定义类型,需要用 #[derive(Debug)] 或手动实现 Debug trait;Display 必须手动实现。
Rust 没有 f-string,但有等效的宏 format!(生成字符串)和 println!(打印输出),配合 {name} 命名参数或 {0}/{1} 位置参数。Python 的 f"hello {name}" 在 Rust 中对应 format!("hello {}", name) 或 format!("hello {name}", name = name)。Rust 的 format! 同样在编译期检查类型安全性。
dbg! 是 Rust 1.32 引入的调试宏,它打印调试信息(包括表达式所在的文件和行号),并返回表达式的值(可以内联使用)。let x = dbg!(a + b); 会打印 [文件名:行号] a + b = 结果,同时 x 的值就是计算结果。这比 println!("{:?}", a + b) 更方便,因为不需要写两次表达式。
println! 输出到标准输出(stdout),eprintln! 输出到标准错误(stderr)。两者的格式化参数完全一致,区别仅在于输出流。在 Unix 系统中,stdout 和 stderr 是分开的流,可以用 command > output.txt 2> error.txt 将正常输出和错误信息分开处理。Rust 标准库还有 print!(无换行)和 eprint!(无换行 + stderr),以及 writeln!/write!(输出到 Write trait 的实现者,如文件或 Vec<u8>)。
match 是表达式(可以返回值),可以用在任何需要表达式的地方,如变量赋值、函数返回值、甚至作为宏的参数。Rust 还提供了简化写法:if let(单模式匹配)、while let(循环匹配)、let else(模式+提前返回)。if let Some(x) = option { ... } 等价于 match option { Some(x) => { ... }, None => { } },语法更简洁。let else 是 Rust 1.65 引入的语法:let Some(x) = option else { return; };,模式不匹配时执行 else 块并提前返回。
全篇必记总纲
Rust 的控制流、运算符和格式化输出都体现了"安全优先 + 显式优于隐式"的设计哲学:if/match 是表达式(返回值),for 遍历迭代器(无三段式),整数溢出有四种显式处理策略,println! 在编译期检查类型安全——相比 C 族语言,Rust 在保持语法简洁的同时消除了大量运行时隐患。
控制流是程序的"神经网络",运算符是"逻辑细胞",格式化输出是"信息输出"——三者共同构成程序行为的基础构件。
What 是什么 if/match/loop/for/while 的语法与特性;运算符分类;格式化宏家族
→
Why 为什么 表达式 vs 语句的区别、match 穷举保证、println! 编译期安全检查的意义
→
How 怎么做到的 match 卫表达式与解构、as 转换规则、Debug/Display trait 实现、Iterator 惰性求值
在 Rust 中,if 是表达式而非语句——这意味着它可以返回值。这个设计来自函数式语言(如 ML、Haskell),让 Rust 可以写出更简洁的条件逻辑。
// Rust:if 是表达式,返回值
let score = 85;
let grade = if score >= 90 {
"A"
} else if score >= 75 {
"B"
} else {
"C"
};
println!("Grade: {}", grade); // Grade: B
// 注意:所有分支必须返回相同类型
// let bad = if x > 0 { "positive" } else { 100 }; // 编译错误:类型不匹配
表达式 vs 语句
match 是 Rust 最强大的控制流工具,比 C 的 switch 更通用、更安全、更表达力强。每个分支可以是表达式,返回 match 的值。
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(u8, u8, u8),
}
fn process(msg: Message) -> i32 {
match msg {
Message::Quit => {
println!("退出");
0
}
Message::Move { x, y } => {
println!("移动到 ({}, {})", x, y);
x + y
}
Message::Write(text) => {
println!("写: {}", text);
text.len() as i32
}
Message::ChangeColor(r, g, b) => {
(r as i32) + (g as i32) + (b as i32)
}
}
}
let x = 7;
// 范围匹配(包含两端)
match x {
1..=5 => println!("小"),
6..=10 => println!("大"),
_ => println!("超出范围"),
}
// 卫表达式(Guard):在模式匹配后加条件
match x {
n if n > 0 && n % 2 == 0 => println!("正偶数"),
n if n < 0 => println!("负数"),
_ => println!("其他"),
}
// 多重匹配(用 | 合并)
match x {
1 | 2 | 3 => println!("1~3"),
4 | 5 => println!("4~5"),
_ => {},
}
// 解构元组
let point = (3, 4);
match point {
(0, 0) => println!("原点"),
(x, 0) => println!("X轴: {}", x),
(0, y) => println!("Y轴: {}", y),
(x, y) if x == y => println!("对角线"),
_ => {},
}
Rust match 的穷举检查
Rust 编译器强制检查 match 是否穷举了所有可能。如果有遗漏,编译器会列出缺少哪些变体,并提示用 _ 作为通配符捕获。这在 C 中是 switch 最大的安全隐患——忘了写 default,程序不会报错,但会产生未定义行为。Rust 在编译期就消灭了这个问题。
if let 是 match 的简化语法,用于只关心一个特定模式的情况:
// match 全写
match maybe_value {
Some(x) => println!("got: {}", x),
None => {},
}
// if let 简化版
if let Some(x) = maybe_value {
println!("got: {}", x);
}
// while let:持续从迭代器/Option 中取值,直到模式不匹配
let mut stack = vec![1, 2, 3];
while let Some(top) = stack.pop() {
println!("popped: {}", top);
}
// stack.pop() 返回 None 时,while 循环结束
loop 是无限循环,它最独特的能力是通过 break value 返回值——这是 C 族语言中根本没有的特性:
// loop + break value:Rust 的"有返回值的无限循环"
let result = loop {
let random = compute_something();
if random == 42 {
break random; // 从 loop 中返回值
}
if limit_reached() {
break -1; // 也可以返回错误码
}
};
// 带标签的 break:从深层嵌套循环中直接退出
'outer: for i in 0..10 {
for j in 0..10 {
if condition(i, j) {
println!("Found at ({}, {})", i, j);
break 'outer; // 直接退出外层循环
}
}
}
Rust 的 for 循环只能遍历迭代器,不支持 C 式的三段式循环。这体现了 Rust"迭代器即循环"的哲学:
// Rust for: 遍历迭代器
let arr = [10, 20, 30];
for item in arr.iter() {
println!("{}", item);
}
// 0..n 等价于 C 的 for (i = 0; i < n; i++)
for i in 0..5 {
println!("i = {}", i); // 0, 1, 2, 3, 4
}
// ..= 是包含末尾的范围
for i in 0..=5 {
println!("i = {}", i); // 0, 1, 2, 3, 4, 5
}
// 反向遍历
for i in (0..5).rev() {
println!("i = {}", i); // 4, 3, 2, 1, 0
}
// .enumerate() 同时获取索引和值
for (index, value) in arr.iter().enumerate() {
println!("[{}] = {}", index, value);
}
设计精髓:Rust 为什么废弃三段式 for?
Rust 社区认为 C 式的三段式 for 循环是"隐藏的微型语言",容易写出 off-by-one 错误和复杂的循环变量更新逻辑。Rust 的 for item in iterator 强制使用迭代器API,让开发者写出更安全的代码。如果确实需要三段式循环,可以用 while + 手动管理的循环变量来模拟。
| 类别 | 运算符 | 示例 | 说明 |
|---|---|---|---|
| 算术 | + - * / % | 5 + 3 | 整数除法向零取整(Rust),C 向负无穷取整 |
| 位运算 | & | ^ << >> | 0b1010 & 0b1100 | 逐位操作,右操作数必须是 usize |
| 比较 | == != < > <= >= | a == b | 返回 bool,无隐式转换(比 JS 更严格) |
| 逻辑 | && || ! | a && b | 短路求值,返回 bool(非整数) |
| 范围 | a..b a..=b | 0..10 | Range / RangeInclusive,用于 for 循环和切片索引 |
| 类型转换 | as | i32 as u64 | 编译期转换,无运行时开销 |
| 赋值 | = += -= *= /= %= &= |= ^= <<= >>= | a += 1 | 复合赋值,支持所有二元运算符 |
| 宏 | 输出流 | 换行 | 返回值 | 典型用途 |
|---|---|---|---|---|
| println! | stdout | 是 | () | 标准输出(生产) |
| print! | stdout | 否 | () | 同一行多次打印 |
| eprintln! | stderr | 是 | () | 错误信息、调试输出 |
| eprint! | stderr | 否 | () | stderr 无换行 |
| format! | 不输出(返回 String) | 可选 | String | 字符串插值、拼接 |
| writeln! | 任意 Write | 是 | Result | 文件写入、网络发送 |
| dbg! | stderr(带文件/行号) | 是 | 表达式的值 | 快速调试 |
let name = "Alice";
let age = 30;
let pi = 3.14159;
// {} Display:用户友好输出(需要类型实现 Display trait)
println!("Name: {}", name); // Name: Alice
println!("Age: {}", age); // Age: 30
println!("Pi: {}", pi); // Pi: 3.14159
// {:?} Debug:调试输出(自动为大部分类型 derive)
println!("{:?}", (1, "hello")); // ("hello", 1) — 元组自动 Debug
println!("{:#?}", vec![1, 2]); // [
// 1,
// 2,
// ]
// {:p} 指针地址
let x = 42;
println!("{:p}", &x); // 0x7fff5fbff8ac
// {:b} / {:x} / {:o} 数进制
println!("{:#b}", 42); // 0b101010
println!("{:#x}", 42); // 0x2a
println!("{:#o}", 42); // 0o52
// {:0>5} 填充对齐
println!("{:0>5}", 42); // 00042
println!("{:>10}", "hi"); // " hi"(右对齐)
println!("{:<10}", "hi"); // "hi "(左对齐)
println!("{:^10}", "hi"); // " hi "(居中)
// 命名参数
println!("{name} is {age} years old", name="Bob", age=25);
// 位置参数
println!("{0} + {1} = {2}", 1, 2, 3);
// dbg! 宏
let x = dbg!(2 * 3 + 4); // [src/main.rs:5] 2 * 3 + 4 = 10
// x 的值仍然是 10,但打印了调试信息
格式化参数速记口诀
语句只能执行操作,表达式才能求值。Rust 将 if 设计为表达式,让变量初始化可以包含条件逻辑,无需额外的作用域块:
// C 族语言(需要三元运算符或额外作用域):
// int x = (a > b) ? a : b;
// if (a > b) { x = a; } else { x = b; }
// Rust:if 表达式直接返回值
let x = if a > b { a } else { b };
// 更复杂的场景:条件初始化
let config = if std::env::var("DEBUG").is_ok() {
Config::debug()
} else {
Config::release()
};
// 无需临时变量,逻辑内聚
C 的 switch 有两个主要隐患:忘记写 default(静默忽略未匹配情况)和缺少 break(穿越到下一个分支)。Rust 的 match 消除了这两个问题:
// C 中危险的 switch 穿越(Fall-through):
// switch (x) {
// case 1: printf("one\n");
// // 忘记 break!会继续执行 case 2
// case 2: printf("two\n"); break;
// }
// Rust match:每个分支是独立的,不会穿越
match x {
1 => println!("one"),
2 => println!("two"),
_ => println!("other"), // 必须穷举(或用 _)
}
// Rust 没有 fall-through:每个分支是独立的,不需要 break
C switch 的 fall-through 是一个历史遗留的设计缺陷。它最早来自 BCPL 语言(1967 年),被 C 继承后成为无数 bug 的来源——开发者经常忘记 break,导致逻辑错误。Rust 直接废除了 fall-through,要求每个分支显式处理,消除了这类错误。
三元运算符 cond ? a : b 的存在理由是"if 作为语句不能返回值"。Rust 的 if 本身就能返回值,所以不需要额外的三元运算符。Rust 社区认为,三元运算符虽然简洁,但可读性差(尤其嵌套时),而且 Rust 的分支可以是多行代码块,表达能力远超三元运算符。
C 式的三段式 for 循环(for (init; cond; update))是 C 语言最灵活也最容易出错的语法之一:
Rust 用迭代器抽象统一了遍历语义,for item in iterator 强制使用更安全的 API。如果 Rust 觉得迭代器 API 不够用,可以用 while + 手动管理循环变量来模拟三段式。
printf("%s", integer) 在 C 中是未定义行为,但编译器通常不会报错(只是产生垃圾输出)。Rust 的 println! 在编译期通过 fmt trait 系统检查参数类型:如果占位符和参数类型不匹配,编译器直接报错。这让大量运行时格式化错误变成编译期错误。
Rust 格式化系统的安全保障
| 特性 | Rust | C / C++ | Python | Go | Java / JS / TS |
|---|---|---|---|---|---|
| 三元运算符 | 无(if 是表达式) | c ? a : b | a if c else b | if c { a } else { b }(无三元) | c ? a : b(JS/TS) |
| 整数除法取整方向 | 向零取整(-3/2 = -1) | 向零取整(C99+) | 向负无穷取整(-3//2 = -2) | 向零取整 | 向零取整(JS/TS number) |
| 整数溢出 | Debug=panic, Release=wrapping(显式方法可选) | 未定义行为(UB) | 不溢出(任意精度整数) | wrapping | wrapping(JS/TS number 是 IEEE-754) |
| 相等比较(==) | 值比较(PartialEq trait) | 值比较(C++ 可重载) | 值比较(is 是身份比较) | 值比较(无 ==,用 ==) | JS: ==(隐式转换),===(严格) |
| 移位右操作数类型 | 必须是 usize,超位 panic/wrap | 可以是任意整数,超位是 UB | 无位运算(用函数) | 必须是 unsigned int | JS/TS: 右操作数取低 5 位(32 位) |
| 逻辑运算返回类型 | bool | int(0 或 1) | bool | bool | bool(JS/TS) |
| 赋值表达式返回值 | let 是语句,不是表达式 | 返回赋值的值(a = b) | 无返回值(Python 3.8+ 的海象运算符有返回值) | 无返回值 | 无返回值 |
| 短路求值 | && || ??(空值合并) | && || | and or not | && || | && ||(JS 还有 ??) |
// Rust: if 是表达式,所有分支类型必须一致
let x = if n > 0 { "positive" } else { "non-positive" };
// C: if 是语句,三元运算符用于需要值的地方
int x = n > 0 ? 1 : 0;
// Python: if 是表达式(Python 3 的 := 可以返回值,但 if/else 表达式语法不同)
x = "positive" if n > 0 else "non-positive"
// Go: if 是语句,没有三元运算符,用 if 块代替
var x string
if n > 0 { x = "positive" } else { x = "non-positive" }
// Java: if 是语句,三元运算符可用
String x = n > 0 ? "positive" : "non-positive";
// JS/TS: 有三元运算符,== vs === 的类型转换问题
const x = n > 0 ? "positive" : "non-positive";
// Rust match: 强制穷举,无 fall-through,卫表达式,多模式
match x {
1..=5 | 7 => println!("special"),
n if n % 2 == 0 => println!("even"),
_ => println!("other"),
}
// C switch: 非穷举,fall-through,case 只能是常量表达式
switch (x) {
case 1: case 2: case 3: case 4: case 5: case 7:
printf("special\n");
break; // 必须手动 break,否则 fall-through
default:
printf("other\n");
}
// Go switch: 默认不 fall-through(比 C 更安全),但不是穷举
switch x {
case 1, 2, 3, 4, 5, 7:
fmt.Println("special")
default:
fmt.Println("other")
}
// Go 的 switch 也是表达式(可以返回值)
# Python: 没有 switch/match,用 if/elif/else 或字典分发
if x in (1, 2, 3, 4, 5, 7):
print("special")
elif x % 2 == 0:
print("even")
else:
print("other")
# Python 3.10+ 引入 match (结构化模式匹配)
match x:
case 1 | 2 | 3 | 4 | 5 | 7:
print("special")
case n if n % 2 == 0:
print("even")
case _:
print("other")
match vs switch 核心差异总结
| 语言 | 输出语法 | 类型安全 | 格式化能力 |
|---|---|---|---|
| Rust | println!("{}", val) | 编译期检查 | {}(Display)、{:?}(Debug)、{name}(命名)、宽度/对齐/进制 |
| C | printf("%d %s", i, s) | 无(运行时解析) | 宽度、精度、进制(前缀)、浮点格式 |
| C++ | std::cout << x << std::endl; | 流操作符重载,类型安全 | 需要 iomanip(setw、hex 等) |
| Python | print(f"{x}") | f-string 编译期有限检查 | f"{x:.2f}"(格式化)、f"{x!r}"(repr) |
| Go | fmt.Printf("%d %s", i, s) | 编译期类型检查(Go 1.22+) | %v(默认)、%#v(Go-syntax)、%s |
| Java | System.out.printf("%d %s", i, s) | 编译期部分检查 | 格式化字符串(Formatter) |
| JS | console.log(`${x}`) | 模板字符串,无类型转换检查 | 模板字符串插值(${}) |
| TS | console.log(`${x}`) | 模板字符串,类型安全(同 JS) | 模板字符串插值 |
我的理解:Rust 格式化输出 vs Python f-string
Rust 的 println! 和 Python 的 f"hello {x}" 本质上做的是同一件事——把值插入到字符串模板中。但 Rust 的优势在于类型安全(编译期检查占位符和参数类型是否匹配)和格式化能力(宽度、对齐、进制、补零);Python 的优势在于语法更简洁(直接在字符串前加 f)。两者都是现代语言的优秀设计。
// as:编译期数值类型转换(零成本)
let a: i32 = 42;
let b: u64 = a as u64; // i32 -> u64,编译期转换
let c: f64 = a as f64; // i32 -> f64
let d: u8 = a as u8; // 截断:42 -> 42(但 a > 255 时会截断)
// From/Into:更通用的 trait,用于自定义类型
fn process(data: String) { }
let s: String = String::from("hello"); // From 实现
process(s); // Into 自动调用
let s2 = "hello".to_string(); // to_string() 内部调用 From
// 最佳实践:函数参数用 Into<T>(更灵活),具体转换用 as
fn consume_into(s: impl Into<String>) {
let s = s.into(); // 任意可以转为 String 的类型
}
use std::fmt;
struct Point {
x: f64,
y: f64,
}
// Debug trait:{:?} 输出格式(可 derive,也可以手动实现)
impl fmt::Debug for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Point {{ x: {:.2}, y: {:.2} }}", self.x, self.y)
}
}
// Display trait:{} 输出格式(必须手动实现)
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
let p = Point { x: 1.234, y: 5.678 };
println!("{}", p); // (1.23, 5.68) — Display
println!("{:?}", p); // Point { x: 1.23, y: 5.68 } — Debug
本专题核心要点
| 维度 | Rust 特色 | 其他语言对比 |
|---|---|---|
| 条件表达式 | if 是表达式(无三元运算符) | C/C++/JS 有三元运算符;Go 无三元;Python 有 x if c else y |
| 分支穷举 | match 强制穷举(编译器检查) | C switch 非强制(可选 default);Go/JS/TS 非强制 |
| 格式化类型安全 | println! 编译期检查(fmt trait) | C printf 运行时解析(不安全);C++ iostream 类型安全 |
| 整数溢出 | Debug=panic,Release=wrapping,显式方法可选 | C/C++ UB;Python 不溢出;Go/Java wrapping |
| 运算符重载 | 通过 trait 实现,不能自定义运算符符号 | C++ 自由重载(可在任意位置定义);Python 可以重载任意运算符 |
| 循环返回值 | loop + break value 可以返回值 | C/C++/Go/Python/JS 均不支持循环作为表达式返回值 |
学完本文后,下一步学什么?
作者:左扬 | 发表于 2026 年 | 水平有限,欢迎指正
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。