• 【一起学Rust | 基础篇】rust函数与流程控制详解


    在这里插入图片描述


    前言

    在之前的学习中,你已经见过Rust中最重要的一个函数——main,他是一个程序的入口函数。本节我们将详细的讲解Rust中的函数和流程控制的部分内容,学习完本期内容,你的代码就会更加丰富。


    一、函数

    函数在Rust中是非常普遍的。用函数来封装一些流程,会提高代码的复用率。Rust 代码中的函数和变量名使用 snake case 规范风格。在 snake case 中,所有字母都是小写并使用下划线分隔单词。这个与python是一致的,如果你经常用python,那么你将特别熟悉,以下就是符合 snake case 风格的字符串

    get_user_name
    set_user_name
    
    • 1
    • 2

    1. 定义函数

    我们在Rust 中通过输入 fn 后面跟着函数名和一对圆括号来定义函数。大括号告诉编译器哪里是函数体的开始和结尾。一个无参函数的结构如下

    fn function_name(){
    }
    
    • 1
    • 2




    花括号里面包着的,我们称之为——作用域。

    2. 函数参数

    我们可以定义具有参数的函数,参数是特殊变量,是函数签名的一部分。

    注意:函数签名这个关键词特别重要,见到他你就得想到他是定义函数的那段代码

    从定义上来讲,参数分为形参和实参。形参就是定义函数的时候,函数签名里面学的参数,此时它仅仅是个标识,没有实际意义,形参的例子如下所示

    注意:在函数签名中,必须 声明每个参数的类型。当定义多个参数时,使用逗号分隔。

    fn function_name(name: &str, age: u8) {
        print!("{} 已经 {} 岁了", name, age);
    }
    
    • 1
    • 2
    • 3

    这里给函数定义了两个函数,一个是name,是字符串类型的,一个是age是8个bit整数型的。这里就是形参,我们可以在函数里面的表达式和语句中使用,但是单独的这参数是没有意义的,只有传过来才有实际的值,你可以理解为带有标签的占位符。

    还有一种就是实参,实参就是传给函数的实际值,它具有实际的意义。并且它是传递给形参的。以下就是实参传递给形参的例子

    function_name("张三",24);
    
    • 1

    这是一个Rust语句,调用了上面写的function_name函数,并且传入两个参数,一个是字符串类型的张三,一个是整型的24,代表年龄。这就是实参,我们在调用的时候传入的参数就是实参。

    3. 语句和表达式

    函数体由一系列的语句和一个可选的结尾表达式构成。因为 Rust 是一门基于表达式的语言,这是一个需要理解的、不同于其他语言的重要区别。

    语句是执行一些操作但不返回值的指令。表达式计算并产生一个值。

    下面给出一个例子,从中我们学习什么是语句,什么是表达式。

    fn main() {
        let y = {
            let x = 3;
            x + 1
        };
    
        println!("y的值是: {y}");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    一般来说,在Rust中,语句末尾是由分号的,而表达式末尾没有分号,并且需要返回一个值。在上面的代码中


    表达式用花括号包起来,说明表达式是个代码块,代码块里面是语句,最后x+1作为返回值,这个我们接下来就讲。

    4. 函数带返回值

    函数可以向调用它的代码返回值。我们并不对返回值命名,但要在箭头(->)后声明它的类型。在 Rust 中,函数的返回值等同于函数体最后一个表达式的值。这也就是为什么上面代码块最后是个表达式。以下就定义了个具有返回值的函数,

    fn get_age(name: &str) -> u8 {
        return 18;
    }
    
    • 1
    • 2
    • 3

    使用 return 关键字和指定值,可从函数中提前返回;但大部分函数隐式的返回最后的表达式。所以上面的代码还可以这么写

    fn get_age(name: &str) -> u8 {
        18
    }
    
    • 1
    • 2
    • 3

    我们还可以使用变量来接收这个函数的返回值

    let age = get_age();
    
    • 1

    二、流程控制

    根据条件是否为真来决定是否执行某些代码,以及根据条件是否为真来重复运行一段代码的能力是大部分编程语言的基本组成部分。Rust 代码中最常见的用来控制执行流的结构是 if 表达式和循环。

    1. if条件跳转

    if 表达式允许根据条件执行不同的代码分支。你提供一个条件并表示 如果条件满足,运行这段代码;如果条件不满足,不运行这段代码。

    以下是使用if进行条件判断的一个小案例

    fn main() {
        let number = 3;
    
        if number < 5 {
            println!("条件为true");
        } else {
            println!("条件为false");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这里定义了一个变量number,并且赋值为3,后面的if就是条件选择语句了。if后面,花括号之前就是条件,

    条件必须是一个表达式,并且返回True或者False

    后面是两个代码块,一个是条件为true执行的代码块,一个是条件为false执行的代码块。

    现在运行一下看效果

    此时我们将number改成7,再次执行


    判断条件必须是true或者false的表达式,一下是错误用法

    fn main() {
        let number = 3;
    
        if number {
            println!("number是3");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这个用法是错的,Rust没有和C语言那种非0即true的规则。

    else if处理多个条件

    可以将 else if 表达式与 if 和 else 组合来实现多重条件。以下就是处理多个条件的例子,判断一个数字是否可以被2,3,4整除

    fn main() {
        let number = 6;
    
        if number % 4 == 0 {
            println!("number 被 4 整除");
        } else if number % 3 == 0 {
            println!("number 被 3 整除");
        } else if number % 2 == 0 {
            println!("number 被 2 整除");
        } else {
            println!("number 不能被 4, 3, 或 2 整除");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    将if表达式赋值给变量

    可以用if语句返回值,从而作为一个表达式来用,

    fn main() {
        let condition = true;
        let number = if condition { 5 } else { 6 };
    
        println!("number的值是: {number}");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如上,如果condition 是true的话,number就是5,否则就是6,要注意的是,返回的值必须是同一个类型的,因为Rust的类型必须是确定的,以下就是错误的用法

    fn main() {
        let condition = true;
        let number = if condition { 5 } else { "six" };
        println!("number的值是: {number}");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.loop循环

    多次执行同一段代码是很常用的,Rust 为此提供了多种 循环(loops)。一个循环执行循环体中的代码直到结尾并紧接着回到开头继续执行。

    Rust 有三种循环:loopwhilefor

    loop 关键字告诉 Rust 一遍又一遍地执行一段代码直到你明确要求停止。以下是一个使用loop循环的例子,会不断的输出again!

    fn main() {
        loop {
            println!("again!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行如下

    使用ctrl+c以退出循环

    这里我们没有写退出条件,通常我们会使用break来退出循环

    fn main() {
        let mut x = 0;
        loop {
            x += 1;
            if x == 10 {
                break;
            }
            println!("x 的值是: {}", x);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    同时也可以退出并返回值

    fn main() {
        let mut x = 0;
        let result_value = loop {
            x += 1;
            if x == 10 {
                break x;
            }
            println!("x 的值是: {}", x);
        };
        println!("result_value 的值是: {}", result_value);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出结果如下

    循环标签

    循环标签是用来消除多个循环之间的歧义的。如果存在嵌套循环,break 和 continue 应用于此时最内层的循环。你可以选择在一个循环上指定一个 循环标签(loop label),然后将标签与 break 或 continue 一起使用,使这些关键字应用于已标记的循环而不是最内层的循环。

    fn main() {
        let mut count = 0;
        'counting_up: loop {
            println!("count = {count}");
            let mut remaining = 10;
            loop {
                println!("remaining = {remaining}");
                if remaining == 9 {
                    break;
                }
                if count == 2 {
                    break 'counting_up;
                }
                remaining -= 1;
            }
            count += 1;
        }
        println!("End count = {count}");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    外层循环有一个标签 counting_up,它将从 0 数到 2。没有标签的内部循环从 10 向下数到 9。第一个没有指定标签的 break 将只退出内层循环。break 'counting_up; 语句将退出外层循环。

    3. while条件循环

    while循环就和其他的编程语言一样,只有满足条件时才循环,以下是while循环的一个例子,

    fn main() {
        let mut number = 3;
        while number != 0 {
            println!("{number}!");
            number -= 1;
        }
        println!("LIFTOFF!!!");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    以上代码实现了一个逻辑,如果number不等于0就执行代码块的内容,也就是number减一,直到运行到符合条件。

    这种结构消除了很多使用 loop、if、else 和 break 时所必须的嵌套,这样更加清晰。当条件为真就执行,否则退出循环。

    4. for循环

    for循环我们主要是用来遍历集合的,在Java中,我们通常称为for循环是while的一个语法糖,实际上while能做的,for也能做,以下是一个while实现的遍历数组

    fn main() {
        let a = [10, 20, 30, 40, 50];
        let mut index = 0;
        while index < 5 {
            println!("值是: {}", a[index]);
            index += 1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里,代码对数组中的元素进行计数。它从索引 0 开始,并接着循环直到遇到数组的最后一个索引(这时,index < 5 不再为真)。并输出该元素。

    如果我们用for循环来遍历就是下面这样的

    fn main() {
        let a = [10, 20, 30, 40, 50];
        for element in a {
            println!("值是: {element}");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这样看起来就简洁了不少,但是要注意关键词in后面必须是一个集合,因此你还可以这么写

    fn main() {
        for element in [10, 20, 30, 40, 50] {
            println!("值是: {element}");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    此外还可以输出range序列,如下就是输出1到10

    fn main() {
        for element in (1..10) {
            println!("值是: {element}");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    总结

    以上就是本期的所有内容。本期主要讲了两部分内容,分别是rust的函数和流程控制。函数主要介绍了函数的定义和函数的有参和无参,形参和实参,还把rust的语句和表达式顺便提了一下。流程控制介绍了常用的几种程序流程控制的语法,循环,条件等。

    如果你也对Rust感兴趣,可以点个关注,与我一起探讨、学习Rust。

  • 相关阅读:
    Netty入门知识点
    mysql主从复制与读写分离
    港联证券:“火箭蛋”来袭 蛋价涨势能否延续?
    MySQL导入sql文件的三种方法
    【微服务】Nacos服务端完成微服务注册以及健康检查流程
    【深度学习实战(41)】保姆级教程:Anaconda + Pycharm 安装
    关于数据链路层(初步)
    arduino32 esp32路舵机驱动板(开源可自制,附程序和固件以及烧录方法)
    Lambda表达式
    Android: edittext禁止输入空格和特殊字符代码记录
  • 原文地址:https://blog.csdn.net/weixin_47754149/article/details/125910031