首页 > 其他分享 >rust学习-函数的定义与使用

rust学习-函数的定义与使用

时间:2025-01-20 18:31:27浏览次数:3  
标签:定义 i32 参数 rust println 返回值 fn 函数

rust学习-函数的定义与使用

1. 函数的基本定义

在Rust中,函数使用fn关键字来定义:

fn say_hello() {
    println!("Hello, world!");
}
  • fn:定义函数的关键字
  • say_hello:函数的名字
  • ():函数的参数列表,当前函数没有参数
  • {}:函数体,包含了函数执行的代码

2. 函数的参数

函数可以接受参数,参数的类型必须在函数签名中明确指定:

fn greet(name: &str) {
    println!("Hello, {}!", name);
}
  • name: &str:函数的参数定义,name是参数的名称,&str是参数的类型(&str表示一个字符串切片)

多个参数

函数可以有多个参数,参数之间用逗号分隔:

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. 返回值

函数可以返回一个值,返回值的类型在函数签名中使用->符号指定:

fn add(x: i32, y: i32) -> i32 {
    x + y
}
  • -> i32:表示函数返回一个i32类型的值
  • x + y:函数的返回值,在Rust中,函数体中的最后一个表达式的值会自动作为返回值,除非使用return关键字提前返回

提前返回

可使用return关键字从函数中间返回一个值:

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. 函数调用

定义函数后,可以通过函数名来调用它,调用函数时,必须提供与函数签名中定义的参数相匹配的参数:

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(非引用类型),则传递所有权,意味着函数内部对该参数的修改不会影响外部变量,因为外部变量的所有权已经被转移给函数了,例如:

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(引用类型),则传递的是引用(借用),意味着函数内部对参数的修改不会影响外部变量,且函数执行完毕后,外部变量仍然拥有所有权,例如:

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)

函数作为参数

可以将函数作为参数传递给另一个函数:

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函数计算一个数的平方,并返回结果

函数作为返回值

可以返回一个函数:

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支持泛型函数,可编写可以处理多种类型的函数,泛型函数使用语法来定义泛型类型参数:

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支持使用文档注释来为函数添加注释,这些注释可以生成文档,文档注释以///开头:

/// 这个函数接受两个整数并返回它们的和
///
/// # Examples
///
/// ```
/// let result = add(3, 4);
/// assert_eq!(result, 7);
/// ```
fn add(x: i32, y: i32) -> i32 {
    x + y
}
  • ///:表示这是一个文档注释
  • #Examples:用于展示示例代码
  • 这些注释可以通过cargo doc命令生成文档

标签:定义,i32,参数,rust,println,返回值,fn,函数
From: https://blog.csdn.net/weixin_42333247/article/details/145258118

相关文章

  • MATLAB专题4 函数
    目录一、函数声明二、函数调用三、匿名函数四、递归函数函数:一个能够实现特定功能的逻辑模块一、函数声明注意基本结构与一些注意事项:函数声明的下一行可以添加注释,可在命令行用help或者lookfor调用二、函数调用注意三种变量:1.局部变量:函数中的变量函数结束后......
  • FastReport调用Delphi中的自定义函数(人民币大写金额)
    人民币大写金额转换函数1functionMoneyToCn(ANumberic:Real):string;2const3s1:string='零壹贰叁肆伍陆柒捌玖';4s2:string='分角元拾佰仟万拾佰仟亿拾佰仟万';56functionStrTran(constS,s1,s2:string):string;7begin8Result:=St......
  • 函数篡改注入
    一、介绍利用函数篡改注入可以避免使用 VirtualAlloc/Ex WinAPI调用,使用新代码替换原始函数的字节,导致函数被替换或不再按预期工作。相反,函数将执行不同的逻辑。要实现这一点,需要一个被践踏的牺牲函数地址(1)选择目标函数本地获取函数地址很简单,但用这种技术获得的主要关注点......
  • linux 将自定义程序做成服务开机自启动
    在linux系统中有很多方式可以将自定义程序设置成开机自启动,本文所述的方式是通过将程序设置成service来实现自启动。在/lib/systemd/system目录下新建hello.service文件touch/lib/systemd/system/hello.servicevim/lib/systemd/system/hello.service[Unit]Descrip......
  • 迅为RK3568开发板SPI驱动指南-mcp2515驱动编写:读寄存器函数
    瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和MaliG522EE图形处理器。RK3568支持4K解码和1080P编码,支持SATA/PCIE/USB3.0外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568支持安卓11和linux系统,主要面向......
  • GBase UCASE 和 UPPER 函数详解
    UCASE 和 UPPER 是两个用于将字符串中的字符转换为大写形式的SQL函数。它们在数据处理、报告生成、文本分析以及各种需要统一字符串格式的场景中非常实用。通过这些函数,用户可以确保数据的一致性,方便后续的比较和分析操作。1. UCASE 和 UPPER 函数的基本语法这两个函数在......
  • C++ 模板(函数模板与类模板)
    原文链接:https://www.cnblogs.com/1873cy/p/18398002模板模板介绍#C++提供了函数模板(functiontemplate)。所谓函数模板。实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来代表。这个通用函数就称为函数模板。凡事函数体相同的函数都可以使用这个模板......
  • 深入Node.js工具函数:前端开发的得力助手
    文章目录引言1.Node.js工具函数基础1.1常用工具函数概述1.2工具函数与前端开发的关联2.核心工具函数解析2.1path模块2.1.1resolve函数2.1.2join函数2.2fs模块2.2.1readFile与writeFile2.2.2mkdir与rmdir2.3util模块2.3.1inherits函数2.3.2inspe......
  • [oeasy]python062_提示符是怎么来的_[词根溯源]prompt_input_输入函数_提示符
    提示符是怎么来的_[词根溯源]prompt_input_输入函数_提示符回忆上次内容上次讲的是从键盘输入变量的值 input函数可以接收到输入字符串存在变量里   添加图片注释,不超过140字(可选) input函数的参数叫prompt......
  • 关于线性筛Euler函数的详细证明&代码
    引言:由于dsfz的集训老师讲的跟**一样太快了,蒟蒻前去听了洛谷网校@disangan233大佬的讲解,在此重构线性筛Euler函数的证明及代码。关于Euler函数\(Euler\)函数,同时被称为欧拉函数,定义:\(\varphi(n)\)表示\(\len\)且与\(n\)互质的数的个数我们规定:\(\varphi(1)=1\)Eu......