一、函数
Rust 代码中的函数和变量名使用 snake case 规范风格。在 snake case 中,所有字母都是小写并使用下划线分隔单词。Rust函数的基本形式:
fn <函数名> ( <参数> ) { <函数体>}
fn main() {
println!("Hello, world!");
another_function(); //调用another_function函数
}
fn another_function() {
println!("Another function.");
}
可以使用函数名后跟圆括号来调用我们定义过的任意函数。因为程序中已定义 another_ function
函数,所以可以在 main
函数中调用它。注意,源码中 another_function
定义在 main
函数之后;也可以定义在之前。Rust 不关心函数定义所在的位置,只要函数被调用时出现在调用之处可见的作用域内就行。
1.参数
我们可以定义为拥有 参数(parameters)的函数,参数是特殊变量,是函数签名的一部分。当函数拥有参数(形参)时,可以为这些参数提供具体的值(实参)。
fn main() {
println!("Hello, world!");
another_function(5);
}
fn another_function(x: i32) {
println!("The value of x is: {x}");
}
运行此段代码,将会得到如下输出:
another_function
的声明中有一个命名为 x
的参数。x
的类型被指定为 i32
。当我们将 5
传给 another_function
时,println!
宏会把 5
放在格式字符串中包含 x
的那对花括号的位置。
在函数签名中,必须声明每个参数的类型。这是 Rust 设计中一个经过慎重考虑的决定:要求在函数定义中提供类型注解,意味着编译器再也不需要你在代码的其他地方注明类型来指出你的意图。而且,在知道函数需要什么类型后,编译器就能够给出更有用的错误消息。
fn main() {
println!("Hello, world!");
another_function(5);
}
fn another_function(x) { //错误,未声明参数x的类型
println!("The value of x is: {x}");
}
当定义多个参数时,使用逗号分隔,像这样:
fn main() {
print_labeled_measurement(5, 'h');
}
fn print_labeled_measurement(value: i32, unit_label: char) {
println!("The measurement is: {value}, {unit_label}");
}
2.语句和表达式
Rust 是一门基于表达式(expression-based)的语言,这是一个需要理解的(不同于其他语言)重要区别。其他语言并没有这样的区别,所以让我们看看语句与表达式有什么区别以及这些区别是如何影响函数体的。语句(Statements)是执行一些操作但不返回值的指令。 表达式(Expressions)计算并产生一个值。
fn main() {
let y = 6;
}
let y = 6;
是一个语句。函数定义也是语句,上面整个例子本身就是一个语句,语句不返回值,因此,不能把 let
语句赋值给另一个变量,比如下面的例子尝试做的,会产生一个错误:
fn main() {
let x = (let y = 6);
}
let y = 6
语句并不返回值,所以没有可以绑定到 x
上的值。这与其他语言不同,例如 C 和 Ruby,它们的赋值语句会返回所赋的值。在这些语言中,可以这么写 x = y = 6
,这样 x
和 y
的值都是 6
;Rust 中不能这样写。
表达式有计算步骤且有返回值,表达式会计算出一个值。考虑一个数学运算,比如 5 + 6
,这是一个表达式并计算出值 11
。表达式可以是语句的一部分。函数调用是一个表达式。宏调用是一个表达式。用大括号创建的一个新的块作用域也是一个表达式,例如:
fn main() {
let y = {
let x = 3;
x + 1
};
println!("The value of y is: {y}");
}
其中,let y= 后边的花括号中是一个代码块,它的值是4,这个值作为 let
语句的一部分被绑定到 y
上。注意 x+1
这一行在结尾没有分号,表达式的结尾没有分号。如果在表达式的结尾加上分号,它就变成了语句,而语句不会返回值。在接下来探索具有返回值的函数和表达式时要谨记这一点。
3.具有返回值的函数
函数可以向调用它的代码返回值。我们并不对返回值命名,但要在箭头(->
)后声明它的类型。在 Rust 中,函数的返回值等同于函数体最后一个表达式的值。使用 return
关键字和指定值,可从函数中提前返回;但大部分函数隐式的返回最后的表达式。这是一个有返回值的函数的例子:
fn five() -> i32 {
5
}
fn main() {
let x = five();
println!("The value of x is: {x}");
}
在 five
函数中没有函数调用、宏、甚至没有 let
语句 —— 只有数字 5
。这在 Rust 中是一个完全有效的函数。注意,也指定了函数返回值的类型,就是 -> i32
。函数体只有单单一个 5
也没有分号,因为这是一个表达式,我们想要返回它的值。
fn main() {
let x = plus_one(5);
println!("The value of x is: {x}");
}
fn plus_one(x: i32) -> i32 {
x + 1
}
fn main() {
let x = plus_one(5);
println!("The value of x is: {x}");
}
fn plus_one(x: i32) -> i32 {
x + 1;
//错误,加了分号后变成了语句,不再是表达式,
//函数 plus_one 的定义说明它要返回一个 i32 类型的值,不过语句并不会返回值,
//使用单位类型 () 表示不返回值。因为不返回值与函数定义相矛盾,从而出现一个错误。
}
注意以下两种写法:
fn add1(a: i32, b: i32) -> i32 {
return a + b;
}
fn add2(a: i32, b: i32) -> i32 {
a + b
}
两种写法都是正确的,测试一下这两种写法:
fn main() {
let x = add1(1,2);
let y = add2(3,4);
println!("The value of x(add1) is {x}");
println!("The value of y(add2) is {y}");
}
fn add1(a: i32, b: i32) -> i32 {
return a + b;
}
fn add2(a: i32, b: i32) -> i32 {
a + b
}
输出结果:
return关键字可以用来提前结束函数的执行,如:
fn is_positive(num: i32) -> bool {
if num > 0 {
return true;
}
false
}
如果没有使用 return
语句,函数会默认返回 false
,因为 if
表达式的最后一个值是 ()
,也就是空类型,而 ()
可以被隐式转换为 false
。
二、 if表达式
if
表达式允许根据条件执行不同的代码分支。你提供一个条件并表示 “如果条件满足,运行这段代码;如果条件不满足,不运行这段代码。
fn main() {
let number = 3;
if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}
可以将 else if
表达式与 if
和 else
组合来实现多重条件。例如:
fn main() {
let number = 6;
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else if number % 2 == 0 {
println!("number is divisible by 2");
} else {
println!("number is not divisible by 4, 3, or 2");
}
}
if
的每个分支的可能的返回值都必须是相同类型;上边例子if
分支和 else
分支的结果都是 i32
整型。如果它们的类型不匹配,则会出现错误
因为 if
是一个表达式,我们可以在 let
语句的右侧使用它:
fn main() {
let condition = true;
let number = if condition { 5 } else { 6 };
println!("The value of number is: {number}");
}
三、循环
Rust 有三种循环:loop
、while
和 for
。
loop
关键字告诉 Rust 一遍又一遍地执行一段代码直到你明确要求停止。
fn main() {
loop {
println!("again!");
}
}
当运行这个程序时,我们会看到连续的反复打印 again!
,直到我们手动停止程序。大部分终端都支持一个快捷键,ctrl-c,来终止一个陷入无限循环的程序。也可以使用 break
关键字来告诉程序何时停止循环。
loop
的一个用例是重试可能会失败的操作,比如检查线程是否完成了任务。然而你可能会需要将操作的结果传递给其它的代码。如果将返回值加入你用来停止循环的 break
表达式,它会被停止的循环返回:
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {result}");
}
可以得到输出:
while循环:
fn main() {
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("the value is: {}", a[index]);
index += 1;
}
}
for循环:
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
}
fn main() {
for number in (1..6).rev() {
println!("{number}!");
}
println!("LIFTOFF!!!");
}
输出:
Rust语言基础教程学习其他章节【未完待续】:
Rust语言基础教程学习【一】:Rust语言基础教程学习【一】(Rust基础语法、数据类型)_LLLL、的博客-CSDN博客
Rust语言基础教程学习【三】:Rust语言基础教程学习【三】(所有权)_LLLL、的博客-CSDN博客
Rust语言基础教程学习【四】:Rust语言基础教程学习【四】(结构体)_LLLL、的博客-CSDN博客
Rust语言基础教程学习【五】:Rust语言基础教程学习【五】(枚举和模式匹配)_LLLL、的博客-CSDN博客
Rust语言基础教程学习【六】:Rust语言基础教程学习【六】(包、Crate、模块)_LLLL、的博客-CSDN博客
Rust语言基础教程学习【七】: Rust语言基础教程学习【七】(常见集合)_LLLL、的博客-CSDN博客