Rust之抽空学习系列(四)—— 编程通用概念(下)

news/2024/12/17 3:20:18/

Rust之抽空学习系列(四)—— 编程通用概念(下)

1、函数

函数用来对功能逻辑进行封装,能够增强复用、提高代码的可读

以下是函数的主要组成部分:

  • 名称
  • 参数
  • 返回类型
  • 函数体

1.1、函数名称

在Rust中,函数通过fn关键字进行声明,并且函数的名称遵循蛇形命名法,即名称使用小写字母进行组合,单词与单词之间使用下划线进行分割,这点倒是和Python中的函数命名方式倒是相一致的

其实,在Rust中函数和变量通常都应该采用蛇形命名法

维基百科:蛇形命名法

rust">fn make_money() {   // 蛇形命名法println!("赚钱");
}fn main() {   // 作为入口的main()函数// 函数调用,函数名加(参数),现在没有参数就是()make_money();  
}

刚刚是先定义的函数,再在main中进行调用,这个顺序反过来也不影响,这个可以和某些编程语言的写法区分一下

rust">fn main() {make_money();
}
// 放在后面也可以
fn make_money() {println!("赚钱");
}

函数可以先定义或后定义,只要对于使用区域可见即可

1.2、函数参数

函数的参数可以将外部的变化灵活地告诉内部的逻辑,在框架不变的前提下随机应变,作为函数签名的一部分,就像在文档上看到的那样
在这里插入图片描述

rust">fn main() {make_money(3);     // 传入具体的参数
}fn make_money(times: i32) {    // 定义可传入的参数println!("赚钱{}次", times);
}

在函数签名当中,需要显式声明每个参数的类型(Rust的设计者慎重考虑的结果),以便于编译器根据其他部分的代码进行推导后能明确意图,显式地标准总好过复杂的外部情形,对吧?

而对于需要传入多个函数参数的场景,参数彼此直接使用,间隔开即可

rust">fn main() { make_money(3, 100);
}
// 多个参数,指出类型,“,”分隔
fn make_money(times: i32, value: i32) {println!("赚钱{}次, 每次{}", times, value);
}

函数中的语句和表达式

先来了解下两个概念:语句和表达式

  • 语句是执行操作但是不返回值的指令
  • 表达式是会进行计算并且得到一个值作为结果的指令

维基百科:语句&语句与表达式的区别

这样看来,表达式最终还是可以换成某个变量表示的,就像数学计算里一样,我们列了一长串计算的式子,最终的目的也只是为了一个计算结果
在这里插入图片描述
图中绿框的部分是语句,因为它们没有返回值,只是在描述一步步地操作,但是第二条语句的右侧红框部分是一条表达式,描述了sentence变量与234比较的结果,最终返回了bool类型

rust">let sentence = 125;let result = {let temp = sentence / 2 ;temp == 234   // 没有分号,用作表达式返回
};

还有些复杂些的场景(比如套{}的多行语句),在末尾使用表达式,不带分号可以返回结果,因为表达式不包括分号的部分

1.3、函数返回值

函数的返回值也是签名的一部分,可以向调用者返回值,使用->表示,并在其后面声明其类型

可以使用return直接返回值或者函数体中最后一个表达式的值进行返回

rust">fn sum(a: i32, b: i32) -> i32 {   // 定义类型a + b   // 表达式返回
}
rust">let result = sum(3, 2);  // 返回5
println!("result={}", result);

如果为函数的表达式结果加上分号,那么就会变成语句,进而无法匹配返回值类型

在这里插入图片描述

在这里插入图片描述
可以从报错信息中看出,此时返回值类型不匹配,现在改成语句后编译器接收到的是(),似乎是空元组,那么其实也可以推测出语句默认返回的值就是空元组了,这正好对应了没有返回值的函数,其实它们的返回值()只是没有体现在代码中

在这里插入图片描述
如果体现出来,可以写成这样,没有返回值的函数其实也是隐含了一个类型的

2、控制流

程序往往不是平铺直叙的,需要包含循环、判断等控制逻辑使其更加丰满

2.1、if 表达式

if表达式主要是根据条件选择分支,许多的编程语言中都有类似的表达

rust">let assets = 100;
if assets < 100 {  // 条件分支println!("穷人")
} else if assets >= 100 && assets < 10_000 {println!("普通工薪阶级")
} else {    // 兜底println!("大佬")
}

if会计算对应分支的条件表达式的bool值,为true则执行对应的代码块的内容,为false则将跳过整个代码块(Rust不会尝试将非布尔类型的值转换为布尔类型
并且,else ifelse总是伴随if,一同组成多条件的分支

接下来,还是需要继续强调一下if表达式作为表达式的属性,由于if其实是表达式,那么本身能够返回值,因此可以直接将if的整体判断和返回内容一同放置到值的位置上

rust">let assets = 100;
let identity = if assets < 100 {    // 表达式作为右值"穷人"   // 返回值
} else if assets >= 100 && assets < 10_000 {  "普通工薪阶级"
} else {"大佬"
};
println!("身份={}", identity);    

这里对于原来的内容进行了改写,将if判断结构直接作为赋值语句的右值使用

需要注意的一点是,在使用if对于条件进行判断的时候,要确保所有分支返回的类型要统一
Rust编译器需要在编译的时候确认分支返回的类型,需要是某个确定的类型
在这里插入图片描述
在这里插入图片描述
上图这种就是一个返回了字符串字面量,而另一个分支是一个整数,显然不好确定嘛

2.2、循环

计算机很擅长做重复的工作,并且这样的工作也非常适合它们

在各种编程语言中,提供的循环的结构也都大同小异,Rust也是基于这些原型进行一些优化和改造

Rust提供了3种循环:

  • loop
  • while
  • for
2.2.1、loop循环

使用loop{}可以定义一段无限循环

rust">loop {print!("放我出去!")
}

但是,通常我们不会进行无意义的无限循环,还是需要满足一定的条件的时候让它处理一些事情,这个时候就需要使用break跳出

rust">let mut i = 1;
let result = loop {i += 1;if i % 3 == 1 {break i;   // 满足条件结束并返回 4}
};
println!("result={}", result);
2.2.2、while循环

while循环会在每次执行循环体之前判断一次条件,条件为true就执行,否则就跳出

rust">let mut num = 10;
while num > 0 {println!("倒数={}", num);num -= 1;
}

在这里插入图片描述

2.2.3、for循环

使用for最大的好处是可以方便地遍历数组、元组等容器里的元素

rust">let teams = ["姆巴佩", "哈兰德", "克瓦拉茨赫利亚", "贝林厄姆", "穆德里克"];
println!("开始点名!");
for player in teams.iter() {println!("{}", player);
}

在这里插入图片描述

在遍历元素方面,for显得更加安全简洁

rust">for i in 0 .. teams.len() {   // 也可以使用Range通过区间取出索引println!("{}", i);
}

https://kaisery.github.io/trpl-zh-cn/ch03-05-control-flow.html


http://www.ppmy.cn/news/1555756.html

相关文章

前端性能分析面试题(一)

如何使用 Webpack 进行前端性能优化&#xff1f; Webpack 是一个现代 JavaScript 应用程序的静态模块打包器&#xff0c;它可以帮助开发者优化前端性能。以下是一些使用 Webpack 进行前端性能优化的方法&#xff1a; 代码分离&#xff1a;通过多入口文件、自定义分包&#xf…

k8s service 配置AWS nlb load_balancing.cross_zone.enabled

在Kubernetes中配置NLB&#xff08;Network Load Balancer&#xff09;的跨区域负载均衡&#xff08;cross-zone load balancing&#xff09;&#xff0c;需要使用服务注解&#xff08;service annotations&#xff09;来实现。根据AWS官方文档&#xff0c;以下是配置NLB跨区域…

Java面试之单例模式浅谈

单例模式是Java面试中常会问到的一个问题&#xff0c;众所周知&#xff0c;单例模式分为两大部分&#xff1a;饿汉模式和懒汉模式。但是&#xff0c;如果当面试官问道关于单例模式的话&#xff0c;如果你只答出这两种模式&#xff0c;且懒汉模式还是最基础最简陋版的话&#xf…

为每个数据库创建一个RedisTemplate实例,这个如何配置和使用

为每个数据库创建一个RedisTemplate实例通常涉及到配置多个数据源和对应的RedisTemplate。以下是如何在Spring Boot中配置和使用多个RedisTemplate实例的步骤&#xff1a; 1. 配置多个Redis连接工厂 首先&#xff0c;你需要为每个Redis数据库配置一个RedisConnectionFactory。…

Lambda表达式对List对象实现多个动态属性排序

一、 Lambda表达式对List对象实现多个动态属性排序 package com.example.gateway;import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.lang.r…

vue3实现ai聊天对话框

各功能部分学习 input输入 使用keydown 键盘进行操作&#xff0c;回车和点击一样进行搜索 keydown.enter.exact.prevent"handleSend" keydown.enter.shift.exact"newline"按钮 loading 加载图标&#xff1a;这里设置 template 插槽 <el-buttontype&…

【jvm】内存溢出内存不够的原因

目录 1. 内存分配与回收问题2. 代码逻辑问题3. JVM参数设置不当4. 系统资源限制 1. 内存分配与回收问题 1.堆内存不足&#xff1a;应用程序申请的内存超过了JVM堆内存的限制&#xff0c;导致内存溢出。代码中可能存在内存泄漏&#xff0c;即对象在不再需要时仍被引用&#xff…

搭建一个微服务需求注意的安全问题

在微服务架构中&#xff0c;安全问题是非常重要的考虑因素&#xff0c;因为每个服务都是独立部署的&#xff0c;这增加了攻击面。以下是一些常见的安全措施&#xff0c;可以帮助保护微服务中间件的安全&#xff1a; 认证和授权 OAuth2 和 OpenID Connect&#xff1a;使用 OAu…