变量
在 Rust 中,你可以使用 let
关键字来声明变量。
例如:
#![allow(unused)] fn main() { let x = 42; }
上面我们定义了一个变量 x
并给它赋值为 42
。
类型
Rust 中的每个变量都必须具有一个类型,这个类型可以由编译器推断定,或者由开发者显式指定。
显式类型标注
你可以通过在变量名后加上 :
再跟上类型的方式来指定变量的类型。例如:
#![allow(unused)] fn main() { // let <variable_name>: <type> = <expression>; let x: u32 = 42; }
在上述示例中,我们明确地将 x
的类型约束为 u32
。
类型推断
如果我们不指定变量的类型,编译器会根据变量使用的上下文尝试推断其类型。
#![allow(unused)] fn main() { let x = 42; let y: u32 = x; }
在上面的例子中,我们没有指定 x
的类型。
由于 x
被赋给了显式类型为 u32
的 y
,且 Rust 不会自动类型转换,编译器因此推断定 x
的类型为 u32
—— 和 y
的类型一致,这样才能保证程序编译不报错。
推断限制
有时编译器需要一些辅助信息来基于变量的使用情况推断正确的类型。
这种情况下,你会遇到编译错误,编译器会要求你提供显式类型提示以消除歧义。
函数参数也是变量
不是所有英雄都穿披风衣,也不是所有变量都用 let
声明。
函数参数也是变量!
#![allow(unused)] fn main() { fn add_one(x: u32) -> u32 { x + 1 } }
在上述示例中,x
是类型为 u32
的变量。
x
和用 let
声明的变量唯一区别在于,函数参数必须显式*声明类型。编译器不会为你推断。
这一约束使得 Rust 编译器(以及我们人类!)能在不看实现细节的情况下理解函数的签名,大大提升了编译速度1!
初始化
声明变量时不必立即初始化。
例如:
#![allow(unused)] fn main() { let x: u32; }
是一个有效的变量声明。
但是,在使用变量之前必须初始化它。否则编译器会报错:
#![allow(unused)] fn main() { let x: u32; let y = x + 1; }
会导致编译错误:
error[E0381]: used binding `x` isn't initialized
--> src/main.rs:3:9
|
2 | let x: u32;
| - binding declared here but left uninitialized
3 | let y = x + 1;
| ^ `x` used here but it isn't initialized
|
help: consider assigning a value
|
2 | let x: u32 = 0;
| +++
参考
- 本节练习位于
exercises/02_basic_calculator/02_variables
1
Rust 编译器在提升编译速度方面需要一切可能的帮助。