函数是一组一起执行一个任务的语句块。每个 Rust 程序都至少有一个函数,即主函数 main()
。划分的标准是每个函数执行一个单一的任务。这也是软件设计中经常说的 单一职责。这会让你的代码可读性更好。
函数的定义
定义函数时必须以 fn
关键字开头,fn
关键字是 function
的缩写。
函数名称的命名规则和变量的命名规则一致。
代码语言:txt复制fn 函数名称([参数:数据类型]) -> 返回值 {
// 函数代码
}
- 参数用于将值传递给函数内部的语句。参数是可选的。
- 一个 “不” 返回值的函数。实际上会返回一个单元类型
()
。当函数返回()
时,函数签名可以省略返回类型。
代码语言:txt复制函数(function)使用 fn 关键字来声明。函数的参数需要标注类型,就和变量一样,如果函数返回一个值,返回类型必须在箭头 -> 之后指定。函数最后的表达式将作为返回值。也可以在函数内使用 return 语句来提前返一个值,甚至可以在循环或 if 内部使用。
fn hello(){
println!("Hello, rust!");
}
函数调用
函数需要调用才会被执行,否则就是没用的,多余的代码。
语法
代码语言:txt复制fn 函数名称([参数:数据类型]) 返回值{
//函数体
}
如果函数定义没有参数,那么参数是可以省略的。
代码语言:txt复制fn main() {
hello();
}
//输出 Hello, rust!
在 main()函数中调用 hello()函数。
函数返回值
函数在代码执行完成后,除了将控制权还给调用者之外,还可以携带值给它的调用者。函数可以返回值给它的调用者。称为 函数返回值。
Rust 语言的返回值定义语法,在 小括号后面使用 箭头 ( ->
) 加上数据类型 来定义的。
有 return
代码语言:txt复制fn 函数名称() -> 返回类型 {
return 返回值;
}
没有 return
如果函数代码中没有使用 return
关键字,那么函数会默认使用最后一条语句的执行结果作为返回值。
fn 函数名称() -> 返回类型 {
// 业务逻辑
返回值 // 没有分号则表示返回值
}
注:最后一条语句的执行结果,必须和函数定义时的返回数据类型一样,不然会编译会出错 。
代码语言:txt复制fn get_name() -> String {
return String::from("Go语言微服务架构核心22讲");
}
fn get_name2() -> String {
String::from("从0到Go语言微服务架构师")
}
fn main() {
println!("r1:{}", get_name()); //输出 r1:Go语言微服务架构核心22讲
println!("r2:{}", get_name2());//输出 r2:从0到Go语言微服务架构师
}
函数参数
函数参数 是一种将外部变量和值带给函数内部代码的一种机制。函数定义时指定的参数名叫做 形参。同时把调用函数时传递给函数的值叫做 实参。传递的 实参 数量与 形参 数量和类型必须相同。
参数-值传递
值传递 是把传递的变量的值传递给函数的 形参,所以,函数体外的变量值和函数参数是各自保存了相同的值,互不影响。因此函数内部修改函数参数的值并不会影响外部变量的值。
代码语言:txt复制fn double_price(mut price:i32){
price=price*2;
println!("内部的price是{}",price)
}
fn main() {
let mut price=99;
double_price(price); //输出 内部的price是198
println!("外部的price是{}",price); //输出 外部的price是99
}
参数-引用传递
值传递变量导致重新创建一个变量。但引用传递则不会,引用传递把当前变量的内存位置传递给函数。传递的变量和函数参数都共同指向了同一个内存位置。引用传递在参数类型的前面加上 &
符号。
fn 函数名称(参数: &数据类型) {
// 执行逻辑代码
}
fn double_price2(price:&mut i32){
*price=*price*2;
println!("内部的price是{}",price)
}
fn main() {
let mut price=88;
double_price2(&mut price); //输出 内部的price是176
println!("外部的price是{}",price);//输出 外部的price是176
}
星号(***
**) 用于访问变量 price
指向的内存位置上存储的变量的值。这种操作也称为 解引用。 因此 星号(***
**) 也称为 解引用操作符。
复合类型传参
对于复合类型,比如字符串,如果按照普通的方法传递给函数后,那么该变量将不可再访问。
代码语言:txt复制fn show_name(name:String){
println!("充电科目 :{}",name);
}
fn main() {
let name:String = String::from("从0到Go语言微服务架构师");
show_name(name);
println!("调用show_name函数后: {}",name);
}
报错如下
error[E0382]: borrow of moved value: `name`
let name:String = String::from("从0到Go语言微服务架构师");
|---- move occurs because `name` has type `String`, which does not implement the `Copy` trait
|show_name(name);
| ---- value moved here
|println!("调用show_name函数后: {}",name);
| ^^^^ value borrowed here after move