跳转到内容

Rust 函数

函数(function)是一段有名字、可以反复使用的代码。与其一遍又一遍地写同样的步骤,不如把它们放进一个函数里,需要的时候调用它就行。其实你已经用过一个函数了:main。

用 fn 定义函数,然后写出函数名并加上 () 来调用它:

fn greet() {
println!("来自函数的问候!");
}
fn main() {
greet(); // 调用它
greet(); // 再调用一次
}

输出:

来自函数的问候!
来自函数的问候!
▶ 动手试一试

函数真正好用,是在你能把数据交给它处理的时候。这些输入叫作参数(parameter)。在 Rust 里,每个参数的类型都必须写出来:

fn greet(name: &str) {
println!("你好,{name}!");
}
fn main() {
greet("小明");
greet("小红");
}

输出:

你好,小明!
你好,小红!
▶ 动手试一试

参数想要几个都可以,用逗号隔开:

fn describe(name: &str, age: u32) {
println!("{name} 今年 {age} 岁");
}
fn main() {
describe("Ferris", 10);
}

输出:

Ferris 今年 10 岁
▶ 动手试一试

传进去的值会按位置对应到参数上:第一个值给 name,第二个给 age。如果顺序写反了,比如 describe(10, "Ferris"),类型对不上,就会出现编译错误。

函数可以把一个值交还给调用它的地方。在箭头 -> 后面声明返回类型:

fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let sum = add(3, 4);
println!("3 + 4 = {sum}");
}

输出:

3 + 4 = 7
▶ 动手试一试

注意上面例子里的 a + b 没有分号。这是 Rust 的一个关键概念:

  • 不带分号的表达式,就是要返回的值。
  • 加上分号,它就变成了一条语句,什么也不返回。

所以下面这段代码会出错:

fn add(a: i32, b: i32) -> i32 {
a + b; // ❌ 分号的意思是“什么都不返回”,可我们承诺了要返回 i32
}

编译器会抱怨:这个函数应该返回 i32,却没有返回。只要把最后一行的分号去掉就好了。

fn square(n: i32) -> i32 {
n * n
}
fn main() {
let result = square(5);
println!("5 的平方是 {result}");
}

输出:

5 的平方是 25
▶ 动手试一试

写一个函数 to_fahrenheit,它接收一个 f64 类型的摄氏温度,返回对应的华氏温度。公式是 c * 9.0 / 5.0 + 32.0。分别用 0、100 和 37 度调用它。提示:函数签名是 fn to_fahrenheit(c: f64) -> f64,函数体只需要一个不带分号的表达式。

查看答案
fn to_fahrenheit(c: f64) -> f64 {
c * 9.0 / 5.0 + 32.0
}
fn main() {
println!("0°C 等于 {}°F", to_fahrenheit(0.0));
println!("100°C 等于 {}°F", to_fahrenheit(100.0));
println!("37°C 等于 {}°F", to_fahrenheit(37.0));
}

输出:

0°C 等于 32°F
100°C 等于 212°F
37°C 等于 98.6°F
▶ 动手试一试

注意我们传的是 0.0 而不是 0。参数是 f64,Rust 不会偷偷帮你把整数变成浮点数。当一个 f64 没有小数部分时,{} 打印出来不带 .0,所以你看到的是 32 而不是 32.0。

写一个函数 largest(a: i32, b: i32, c: i32) -> i32,返回三个数中最大的那个。用 (3, 9, 4) 和 (-2, -8, -5) 测试一下。提示:在 Rust 里 if 是表达式(见 if…else),所以一串 if / else if / else 可以作为函数的最后一行。

查看答案
fn largest(a: i32, b: i32, c: i32) -> i32 {
if a >= b && a >= c {
a
} else if b >= c {
b
} else {
c
}
}
fn main() {
println!("{}", largest(3, 9, 4));
println!("{}", largest(-2, -8, -5));
}

输出:

9
-2
▶ 动手试一试

每个分支都没有以分号结尾。每个分支都是一个表达式,整个 if 链会给出其中一个值,这个值就成了返回值。用 >= 而不是 >,可以保证两个数相等时也能返回结果。

  • 用 fn 定义函数,用 name() 调用函数。
  • 参数是函数的输入,每个参数都需要类型:fn greet(name: &str)。
  • 用 -> Type 声明返回类型。
  • 最后一个不带分号的表达式就是返回值。
  • return value; 也可以用,不过通常只用于提前返回。

小测验

1. 在 Rust 中,函数的每个参数都需要写类型吗?

2. 怎样声明函数的返回类型?

3. 为什么函数末尾的 a + b(没有分号)会成为返回值?

4. 函数定义在调用位置的上面还是下面(比如 main 的上面或下面),有影响吗?

得分: 0 / 4