rust学习-函数的定义与使用
- [1. 函数的基本定义](#1. 函数的基本定义)
- [2. 函数的参数](#2. 函数的参数)
- [3. 返回值](#3. 返回值)
- [4. 函数调用](#4. 函数调用)
- [5. 函数的所有权和借用](#5. 函数的所有权和借用)
- [6. 函数作为参数和返回值](#6. 函数作为参数和返回值)
- [7. 泛型函数](#7. 泛型函数)
- [8. 函数注释(文档注释)](#8. 函数注释(文档注释))
1. 函数的基本定义
在Rust中,函数使用fn关键字来定义:
rust
fn say_hello() {
println!("Hello, world!");
}
- fn:定义函数的关键字
- say_hello:函数的名字
- ():函数的参数列表,当前函数没有参数
- {}:函数体,包含了函数执行的代码
2. 函数的参数
函数可以接受参数,参数的类型必须在函数签名中明确指定:
rust
fn greet(name: &str) {
println!("Hello, {}!", name);
}
- name: &str:函数的参数定义,name是参数的名称,&str是参数的类型(&str表示一个字符串切片)
多个参数
函数可以有多个参数,参数之间用逗号分隔:
rust
fn add(x: i32, y: i32) {
println!("The sum of {} and {} is {}.", x, y, x + y);
}
- x: i32, y: i32:函数有两个参数,x和y,它们的类型都是i32(32位整数)
3. 返回值
函数可以返回一个值,返回值的类型在函数签名中使用->符号指定:
rust
fn add(x: i32, y: i32) -> i32 {
x + y
}
- -> i32:表示函数返回一个i32类型的值
- x + y:函数的返回值,在Rust中,函数体中的最后一个表达式的值会自动作为返回值,除非使用return关键字提前返回
提前返回
可使用return关键字从函数中间返回一个值:
rust
fn divide(x: i32, y: i32) -> Option<i32> {
if y == 0 {
return None; // 提前返回
}
Some(x / y)
}
- Option:表示函数的返回值是一个Option类型,它可以是Some(i32)或None
- return None;:在y == 0的情况下,函数会提前返回None
4. 函数调用
定义函数后,可以通过函数名来调用它,调用函数时,必须提供与函数签名中定义的参数相匹配的参数:
rust
fn main() {
say_hello(); // 调用无参数函数
greet("XiaoMing"); // 调用带有一个参数的函数
add(3, 4); // 调用带有两个参数的函数
let result = add(5, 6); // 调用带有返回值的函数
println!("The result is {}.", result);
}
- say_hello():调用无参数的函数
- greet("XiaoMing"):调用带有一个参数的函数,传入字符串"XiaoMing"
- add(3, 4):调用带有两个参数的函数,传入3和4
- let result = add(5, 6):调用带有返回值的函数,并将返回值存储在变量result中
5. 函数的所有权和借用
Rust的所有权系统对函数参数的处理有一些特殊的规则,当将一个变量传递给函数时,Rust会根据参数的类型来决定是传递所有权还是借用
传递所有权
如果参数类型是T(非引用类型),则传递所有权,意味着函数内部对该参数的修改不会影响外部变量,因为外部变量的所有权已经被转移给函数了,例如:
rust
fn take_ownership(s: String) {
println!("Inside function: {}", s);
} // 这里s离开作用域,内存被释放
fn main() {
let my_string = String::from("Hello");
take_ownership(my_string); // my_string的所有权被转移
// println!("{}", my_string); // 这里会报错,因为my_string的所有权已被转移
}
借用
如果参数类型是&T(引用类型),则传递的是引用(借用),意味着函数内部对参数的修改不会影响外部变量,且函数执行完毕后,外部变量仍然拥有所有权,例如:
rust
fn borrow(s: &String) {
println!("Inside function: {}", s);
} // 这里s离开作用域,但不会释放内存,因为只是借用
fn main() {
let my_string = String::from("Hello");
borrow(&my_string); // 传递借用
println!("{}", my_string); // 这里可以正常打印my_string
}
6. 函数作为参数和返回值
Rust支持将函数作为参数传递给其他函数,也可将函数作为返回值返回,这需要使用函数指针(fn)或闭包(Fn trait)
函数作为参数
可以将函数作为参数传递给另一个函数:
rust
fn apply(f: fn(i32) -> i32, x: i32) -> i32 {
f(x)
}
fn square(x: i32) -> i32 {
x * x
}
fn main() {
let result = apply(square, 5); // 将square函数作为参数传递
println!("Result: {}", result); // 输出25
}
- apply函数接受一个函数f作为参数,并调用它
- square函数计算一个数的平方,并返回结果
函数作为返回值
可以返回一个函数:
rust
fn create_greeter(greeting: &str) -> impl Fn(&str) -> String {
move |name| format!("{} {}!", greeting, name)
}
fn main() {
let greeter = create_greeter("Hello");
println!("{}", greeter("XiaoMing")); // 输出 "Hello XiaoMing!"
}
- create_greeter函数返回一个闭包(匿名函数),这个闭包接受一个字符串参数并返回一个新的字符串
- greeter变量存储了返回的闭包,并在调用时使用
7. 泛型函数
Rust支持泛型函数,可编写可以处理多种类型的函数,泛型函数使用语法来定义泛型类型参数:
rust
fn print_twice<T: std::fmt::Debug>(value: T) {
println!("{:?}", value);
println!("{:?}", value);
}
fn main() {
print_twice(3); // 输出3两次
print_twice("Hello"); // 输出"Hello"两次
}
- <T: std::fmt::Debug>:表示T是一个泛型类型,它必须实现了Debug trait(用于格式化输出)
- print_twice函数可以接受任何实现了Debug trait的类型
8. 函数注释(文档注释)
Rust支持使用文档注释来为函数添加注释,这些注释可以生成文档,文档注释以///开头:
rust
/// 这个函数接受两个整数并返回它们的和
///
/// # Examples
///
/// ```
/// let result = add(3, 4);
/// assert_eq!(result, 7);
/// ```
fn add(x: i32, y: i32) -> i32 {
x + y
}
- ///:表示这是一个文档注释
- #Examples:用于展示示例代码
- 这些注释可以通过cargo doc命令生成文档