函数详解
前言
任何一门编程语言几乎都脱离不了:变量、基本类型、函数、注释、循环、条件判断,这是一门编程语言的语法基础,只有当掌握这些基础语法及概念才能更好的学习 Rust。
函数
在 Rust 中,函数是基本的执行单元,本篇将介绍 Rust 中的函数,包括其定义、参数、返回值以及一些注意事项。
函数定义与调用
- Rust 中的函数使用
fn
关键字定义,后跟函数名称和一对圆括号。 - 在圆括号中,可以定义零个或多个参数,每个参数后面跟着一个冒号(
:
)和它的类型。 - 函数体用大括号(
{}
)包围。 - 如果函数需要返回值,必须声明返回类型,通过在参数列表后添加一个箭头(
->
)和返回类型来完成。
1 |
|
示例: 函数 main
是程序的入口,它会调用 another_function
。
1 |
|
参数
函数可以接收零个或者接受多个参数,并为参数指定类型:
1 |
|
在 Rust 中,函数参数是不可变的,需要显式使用mut
关键字标识:
1 |
|
使用mut
关键字使参数可变:
1 |
|
返回值
在 Rust 函数中,返回值的类型紧跟在参数列表之后,并以 ->
开头,返回值通过在函数的最后一个表达式上省略分号来隐式返回的,这将变为函数的返回值。
注意: 最后一个表达式没有分号才作为返回值,如果有分号将作为一个表达式。
1 |
|
在 Rust 中,返回值与最后一个表达式的值有关,并不需要显式的 return
关键字,如果确实需要提前返回,也可以像其他语言那样使用 return
关键字。
1 |
|
私有性
在 Rust 中,默认情况下函数是私有的,只能在定义它们的模块内部访问。与其他语言不同的是,Rust 没有受保护(protected
)、私有的(private
) 关键字,只有 pub
关键字声明是公共的,当函数使用pub
关键字后,才能使函数在其他模块中可见。
1 |
|
可变参数
Rust 不支持直接的可变参数函数(Variadic Functions),但可以通过接受一个切片或者元组来间接实现。
数组可变参数示例
1 |
|
在这个例子中,sum
函数接受一个i32
类型的切片作为参数,并使用迭代器的fold
方法来计算总和。然后就可以通过一个向量调用这个函数,在这种情况下是numbers
向量。将向量的借用&numbers
传递给sum
函数时,它将被自动借用为一个切片,这样函数就可以接受不同数量的参数。
元组可变参数示例
1 |
|
在这个例子中,sum_tuple
函数接受一个包含三个i32
元素的元组。元组在参数列表中是固定大小的,但是可以通过创建不同大小的元组类型来模拟可变参数。但这种方法不如使用切片那样灵活,如果需要不同数量的参数,通常推荐使用切片。
模式匹配 / 参数解构
在 Rust 中,函数参数的行为就像let
绑定一样,这意味着可以在函数定义中直接解构复合类型。例如,倘若你传递一个元组或结构体给函数,可以直接在参数列表中解构它们,从而得到它们的部分或全部内容。
这就像是在let
语句中进行模式匹配,而函数参数就是所匹配的模式。这种特性在处理具有多个部分的数据类型时非常有用,我们无须先创建一个变量,然后再使用模式匹配来解构它,因为我们可以直接在函数的参数中完成这个步骤。
示例:
1 |
|
在这个例子中,print_coordinates
函数接受一个引用到一个元组 (i32, i32)
的参数。参数 &(x, y)
是一个模式,它解构传入的元组,并允许我们在函数体内直接使用 x
和 y
。当我们调用 print_coordinates(&point)
时,point
元组被解构,元组中的值被分别绑定到 x
和 y
。
同样的解构也可以被用在 let
绑定中,例如:
1 |
|
在这里,元组 (1, 2)
被解构,并且值 1
和 2
分别绑定到变量 a
和 b
。
因此,Rust中的参数解构提供了一种非常强大和表达性的方式来处理输入参数,无需手动解构就可以直接取用复合型数据的一部分。
注意事项
rust 中的函数与其他语言有一些差异和需要注意的地方:
- 函数和变量名采用 snake_case 的命名方式。
- Rust 中的函数是表达式,这代表你可以在更大的表达式中嵌套使用它们。
- Rust 不允许函数重载,即在同一作用域中不能有多个同名函数,即使参数类型不同也不行。
- 没有默认参数值或参数名,不能像某些语言那样只提供某些参数。
- 递归函数,即调用自身的函数,在 Rust 中是被允许的,但是需要注意栈溢出的风险。
结语
这是 Rust 基础语法的最后一篇,后面将开始讲解 Rust 所有权、借用等核心基础概念,但这块涉及比较多,加上新年开工比较忙,过段时间在更新相关内容。