在 TypeScript/JavaScript 中,我们定义数字通常极其简单:
1 | |
不管是整数、小数、正数、负数,TS 统统用number搞定(实际上是双精度浮点数)。
但在 Rust 里,为了追求极致的性能和内存控制,这就不够用了。Rust 要求你把数据放进最合适的格子里。
我们先来看看最常用的两种数字类型:
-
有符号整数 (Signed Integers): 以
i开头(integer)。-
可以存负数。
-
例如:
i32(32位整数, Rust 的默认整数类型),i64,i8等。
-
-
无符号整数 (Unsigned Integers): 以
u开头(unsigned)。-
只能存正数(和零)。
-
例如:
u32,u64,u8等。
-
💡 记忆口诀:i 是包含负数 (internet 喷子多,有负能量),u 是只有正数 (you are positive, 你很正能量)。
类型系统的“严格” (Strictness)
在这里,我们需要聊聊 Rust 和 TypeScript 最大的不同。
在 TS 里,你可能习惯了这种操作(虽然不推荐,但它是合法的 JS):
1 | |
但是在 Rust 里,类型检查是极其严格的。就算它们都是“数字”,如果“位宽”或“符号”不一样,它们就不能直接进行运算。
来看看这段代码:
1 | |
由于 age 是 u8,而 year 是 i32,Rust 编译器会报错,拒绝编译。它不会像 JS 那样自动帮你转换类型。
挑战: 为了让这段代码跑通,我们需要把 age 转换成和 year 一样的类型。在 Rust 中,我们使用 as 关键字来进行显式类型转换。
你能猜出怎么修改 let birth_year = year - age; 这一行吗?
(提示:这有点像 TypeScript 的 as number,但你需要指定具体的 Rust 类型)
答案
1 | |
通过 as i32,你显式地把 u8 类型的 age 转换成了 i32,这样它就可以和 year 愉快地相减了。
💡这里的关键点
-
显式转换 (Explicit Casting): JavaScript 经常会在后台偷偷帮你做类型转换(比如字符串加数字),这被称为“隐式转换”。Rust 为了安全,拒绝任何隐式转换。如果你想变,你必须用代码(
as)画押签字。 -
安全隐患: 虽然
u8转i32是安全的(小盒子装进大盒子),但反过来(大转小)可能会导致数据截断(Truncation)。Rust 把这个控制权交给了你,这意味着你得清楚自己在做什么。
🎉第一章通过!
恭喜你完成了 Rust 基础的第一步。我们这一章学到了:
-
变量默认不可变 (
let),想改要加mut。 -
类型更细分 (
i32vsu8),根据数据实际情况选择“容器”。 -
严苛的运算规则,不同类型不能直接算,必须手动
as。