跳转到内容

Rust 语法

现在你已经能运行 Rust 程序了,接下来放慢脚步,看看程序的每个部分到底是什么意思。我们用一个最小的例子,把它一块一块拆开来看。

fn main() {
println!("你好,世界!");
}

输出:

你好,世界!
▶ 动手试一试
fn main() {
// 你的代码在这里运行
}

每个 Rust 程序都从一个名为 main 的函数开始。运行程序时,Rust 会找到 main,然后执行它里面的代码。

  • fn 是定义函数(一段有名字的代码)的关键字。
  • main 是函数名。这个名字很特殊:它是程序的入口。
  • () 里放函数的输入(这里是空的,main 不接收任何输入)。
  • 花括号 { } 包住的是函数体,也就是属于这个函数的代码。

在函数体里,每条指令通常是一条语句(statement),语句以分号 ; 结尾:

fn main() {
let x = 5;
let y = 10;
println!("{}", x + y);
}

输出:

15
▶ 动手试一试

在该加分号的地方漏掉分号,是新手最常犯的错误之一。不过别担心,编译器会直接指出问题在哪儿。

Rust 代码由两种成分组成,而且这两者的区别在 Rust 里比在大多数语言里都重要:

  • 语句会执行某个操作,但不返回值。let x = 5; 就是一条语句。
  • 表达式(expression)会产生一个值。5、x + 1 和 x * 2 都是表达式。

接下来这一点常常让人意外:用花括号 { } 括起来的代码块也是一个表达式。它的值就是最后一行,而且这一行不写分号:

fn main() {
let x = 5;
let y = {
let doubled = x * 2; // 代码块里的一条语句
doubled + 1 // 没有分号:这就是代码块的值
};
println!("y 是 {y}");
}

输出:

y 是 11
▶ 动手试一试

这个代码块先执行里面的语句,再交出 doubled + 1 的结果,也就是 11,于是 y 就等于 11。注意右花括号 } 后面的分号:整行 let y = ...; 仍然是一条语句。

如果在 doubled + 1 后面加上分号,它就不再是代码块的值了。这时代码块返回的是“什么都没有”(Rust 把它写作 ()),而 println! 没法打印它,所以代码无法编译。“最后一行不写分号”这条规则,正是函数返回值的方式。你会在函数一页和把 if 当作表达式时再次见到它。

仔细看 println!:那个感叹号不是笔误。! 表示它是一个宏(macro),而不是普通函数。

现在还不用完全弄懂宏。只要记住一点:看到 !,就说明是宏。目前你唯一会用到的宏,就是用来打印文字的 println!。

fn main() {
println!("这是一次宏调用");
}

在 println! 里,花括号 {} 是占位符,会被你写在文字后面的值依次填上:

fn main() {
let name = "Ferris";
let age = 10;
println!("{} 今年 {} 岁", name, age);
}

输出:

Ferris 今年 10 岁
▶ 动手试一试

也可以把变量名直接写在花括号里,这样通常更清爽:

println!("{name} 今年 {age} 岁");

Rust 不像 Python 那样在意缩进。它靠花括号 { } 来判断代码块从哪里开始、到哪里结束。缩进只是为了让人更容易读懂代码。

话虽如此,Rust 社区有一套标准风格,而且 Rust 自带一个工具,可以自动把代码整理成这种风格:

Terminal window
cargo fmt

运行 cargo fmt 会把你的代码重新排版成官方风格。养成经常用它的习惯吧。

你可以在代码里留下一些 Rust 会忽略的说明文字。这就是注释,以 // 开头:

fn main() {
// 这是一条注释,Rust 会跳过它
println!("你好!"); // 注释也可以写在行尾
}

下一页会更详细地讲注释。

创建两个变量 a = 7 和 b = 3,打印出 7 + 3 = 10。加法让 Rust 来算。提示:一个 println! 可以有多个 {} 占位符,会按顺序用文字后面的值填上。

查看答案
fn main() {
let a = 7;
let b = 3;
println!("{} + {} = {}", a, b, a + b);
}

输出:

7 + 3 = 10
▶ 动手试一试

一家店卖 3 件商品,每件 4 元,另加 2 元运费。用一个 { } 代码块计算 total:在块里先算出 subtotal,再交出 subtotal + 2。打印 总价:14。提示:代码块的最后一行不能有分号。

查看答案
fn main() {
let price = 4;
let quantity = 3;
let total = {
let subtotal = price * quantity;
subtotal + 2 // 运费
};
println!("总价:{total}");
}

输出:

总价:14
▶ 动手试一试
  • 每个程序都从 main 函数开始。
  • 代码写在花括号 { } 里;大多数语句以 ; 结尾。
  • 语句执行操作;表达式产生值。代码块中不带 ; 的最后一行就是它的值。
  • 带 ! 的(比如 println!)是宏。
  • println! 里的 {} 是占位符,由你传入的值来填充。
  • 缩进是为了可读性,运行 cargo fmt 可以自动格式化。

小测验

1. 在 Rust 程序里,main 函数有什么特别之处?

2. println 后面的 ! 是什么意思?

3. 执行 let y = { let a = 2; a + 1 }; 之后,y 的值是多少?

得分: 0 / 3