rust 闭包函数
函数有自己的类型,可以像使用基础类型一样使用函数,包括将函数保存在变量中、保存在 vec 中、声明在结构体成员字段中。闭包函数也是函数,也有自己的类型定义。不过,函数实际上是指针类型,在 rust 所有权中属于借用的关系。
我们声明一个 Vec 对象集,并使用闭包函数做排序。接下来我们自定义一个 City 结构体类型,Vec 中的每个元素都是 City 类型,后面会根据结构体中的 population 属性做排序。
#[derive(Debug)]
struct City {name: String,population: i64,country: String,
}
我们初始化 cities 变量,并向其中依次追加 3 个元素。vec 追加元素使用 push 函数,push 过程也会触发底层数组的扩容。rust 也提供了初始化指定 vec 容量的函数 with_capacity。
fn main() {let mut cities: Vec<City> = vec![];cities.push(City {name: ("上海".to_string()),population: (123i64),country: ("China".to_string()),});cities.push(City {name: ("北京".to_string()),population: (12i64),country: ("China".to_string()),});cities.push(City {name: ("广州".to_string()),population: (124i64),country: ("China".to_string()),});sort_cities(&mut cities);println!("{:?}", cities)
}
sort_cities 算是这篇文章的关键函数了,函数内部使用到了闭包。想要彻底明白下面的逻辑,首先要了解 sort_by_key 函数,这个函数的入参是一个闭包函数。
fn sort_cities(cities: &mut Vec<City>) {cities.sort_by_key(|city| -city.population);
}
声明中的 &mut self 表示方法能够可变地借用 self 实例,支持对它进行修改。闭包函数的类型是 FnMut(&T),返回的类型需要满足 Ord 约束。从声明中可以看出,闭包函数是有类型的,同时,返回的类型必须是可排序的。

代码部分,闭包函数的写法特别简单,两个竖线是闭包函数识别的标志。尽管闭包函数要求有返回值,但代码中并没有体现,都是 rust 自己默认推断实现的。
我们尝试对代码部分的闭包声明做写法上的调整,下面的闭包声明都是相同的。
// 加了代码块
fn sort_cities(cities: &mut Vec<City>) {cities.sort_by_key(|city| {-city.population});
}
// 加了入参声明
fn sort_cities(cities: &mut Vec<City>) {cities.sort_by_key(|city: &City| -city.population);
}
// 加了返回值声明
fn sort_cities(cities: &mut Vec<City>) {cities.sort_by_key(|city| -> i64 { -city.population });
}
闭包引用对象的所有权
在闭包函数体中使用外部的变量,会导致外部变量的所有权发生变更吗?如果是 go 语言,外部变量在闭包中是通过引用来访问的。具体到 rust 语言上,我们可以通过自定义闭包函数验证一番。
我们在原代码基础上做了简化,is_long_name 函数体中直接访问外部变量 sh,并将 sh 的名字重新赋值一个新的变量 name。编译器检测到 sh.name 发生了所有权转移,编译失败。
fn main() {let sh = City {name: ("上海".to_string()),population: (123i64),country: ("China".to_string()),};let is_long_name = || -> bool {let name = sh.name;if name.len() > 2 {true} else {false}};is_long_name();println!("{:?}", sh);
}

在闭包声明的开头,大家也看到过 move 关键字。那么,这个 move 是用来解决什么问题的呢?
针对这个例子,我们专门在闭包内对 sh.name 重新做了赋值运算,变量所有权发生转移也符合认知。那么,我们现在直接使用 sh.name 进行长度判断,对应截图中的第 13 行代码。左右差异点只有:右边的闭包声明中追加生 move 关键字。


rust 中闭包取得数据有两种方式:转移和借用。move 会导致使用到的外部变量发生所有权转移。右边的例子中,闭包中的变量 sh.name 的所有权就发生了转移,导致编译失败。
相关文章:
rust 闭包函数
函数有自己的类型,可以像使用基础类型一样使用函数,包括将函数保存在变量中、保存在 vec 中、声明在结构体成员字段中。闭包函数也是函数,也有自己的类型定义。不过,函数实际上是指针类型,在 rust 所有权中属于借用的关…...
MySQL 实现分库和分表的备份 2023.7.29
1、分库备份 [rootlocalhost mysql-backup]# cat db_bak.sh #!/bin/bash k_userroot bak_password123456 bak_path/root/mysql-backup/ bak_cmd"-u$bak_user -p$bak_password" exc_db"Database|information_schema|mysql|performance_schema|sys" dbname…...
20230728----重返学习-跨域-模块化-webpack初步
day-122-one-hundred-and-twenty-two-20230728-跨域-模块化-webpack初步 跨域 跨域 为什么要跨域? 浏览器为了安全,不能让我们的html文件可以随意引用别的服务器中的文件,只允许我们的html或js文件中,请求我们自己服务器。这个…...
[SQL挖掘机] - 多表连接: union all
介绍: sql中的union all是用于合并两个或多个select语句的结果集的操作符。与union不同的是,union all不会自动去除重复的行,它会简单地将多个查询的结果集合并在一起,包括重复的行。 用法: union all的基本语法如下: select_…...
TypeError: run() got an unexpected keyword argument ‘hide_label‘ yolov5最新版本报错
报错展示 解决方法 把detect.py中的如上部分的 --hide-label改为 --hide-labels,成功解决....
什么是Java中的集成测试?
Java中的集成测试(Integration Test)是一种测试方法,用于测试多个模块或组件之间的交互和集成。在Java中,集成测试通常使用单元测试框架(如JUnit)编写和运行。 对于初学者来说,集成测试可能有些…...
打卡力扣题目二
#左耳听风 ARST 打卡活动重启# 目录 一、问题 二、 解题方法一 三、enumerate函数介绍 关于 ARTS 的释义 —— 每周完成一个 ARTS: ● Algorithm: 每周至少做一个 LeetCode 的算法题 ● Review: 阅读并点评至少一篇英文技术文章 ● Tips: 学习至少一个技术技巧 …...
【Qt】QML-02:QQuickView用法
1、先看demo QtCreator自动生成的工程是使用QQmlApplicationEngine来加载qml文件,下面的demo将使用QQuickView来加载qml文件 #include <QGuiApplication> #include <QtQuick/QQuickView>int main(int argc, char *argv[]) {QGuiApplication app(argc,…...
【IDEA】idea不自动生成target
文章目录 1. 不生成target2. 仅部分文件不生成target2.1. 一般原因就是资源没有设置2.2. 配置编译src/main/java文件夹下的资源文件2.3. 清理缓存(王炸) 3. 参考资料 本文描述idea不生成target的几种情况以及处理方法 1. 不生成target 像下图这样根本就…...
从官网认识 JDK,JRE,JVM 三者的关系
点击下方关注我,然后右上角点击...“设为星标”,就能第一时间收到更新推送啦~~~ JVM 是一些大厂面试必问点,要想解决 OOM、性能调优方面的问题,掌握 JVM 知识必不可少,从今天开始,将为大家介绍 JVM 的常用知…...
python 将pdf文件转图片
有小伙伴问了怎么将 pdf文件转图片的问题,我百度了一波儿,搞了以下python代码给他封装成exe工具了。 中途打包踩了个坑,python进程池的问题,本地运行没啥问题,打包好的exe文件双击就会使电脑内存爆破卡死,…...
js原型以及原型链
目录 原型隐式原型显式原型constructornew操作符 重写原型对象原型链继承原型链继承借用构造函数继承组合构造继承 原型继承寄生继承组合寄生继承 原型继承关系 原型 在JavaScript中,每个对象都有一个内置属性[[prototype]],这个属性指向一个另一个对象…...
Java面向对象编程实战详解(图书管理系统示例)
文章目录 面向编程概念图书管理系统示例需求分析设计阶段编码实现创建目录结构Book类的编码BookList类的编码User类的编码AdminUser类的编码NormalUser类的编码启动类的编写具体的操作实现IOperation接口新增图书的实现借阅图书的实现删除图书的实现显示图书的实现查找图书的实…...
ubuntu设置主机ip
ubuntu 设置ip sudo dhclient -r enp67s0 # 是你的网卡,可以通过ifconfig 查,比如enp0 sudo ifconfig enp67s0 192.168.1.114 netmask 255.255.255.0 Ubuntu显示有线网已连接但无法上网,已经确认网口、交换机(路由器ÿ…...
CleanMyMac X4.14.1中文版如何清理 Mac系统?CleanMyMac 真的能断网激活吗?
CleanMyMac X4.14.1中文版如何清理 Mac系统?Mac系统在使用过程中都会产生大量系统垃圾,如不需要的系统语言安装包,视频网站缓存文件,mac软件卸载残留的注册表等。 随着时间推移,mac系统垃圾就会越来越多,电…...
详细介绍 React 中如何使用 redux
在使用之前要先了解它的配套插件: 在React中使用redux,官方要求安装其他插件 Redux Toolkit 和 react-redux Redux Toolkit:它是一个官方推荐的工具集,旨在简化 Redux 的使用和管理。Redux Toolkit 提供了一些提高开发效率的工具…...
VLOOKUP多条件查询
LOOKUP(1,0/((A3:A15A18)*(C3:C15C18)),F3:F15)...
分页插件Mybatis
<plugins><!-- com.github.pagehelper为PageHelper类所在包名 --><plugin interceptor"com.github.pagehelper.PageInterceptor"><!-- 配置方言:告诉分页插件使用底层数据库是什么--><property name"helperDialect" value"…...
AXI协议之AXILite开发设计(四)—Block Design使用
微信公众号上线,搜索公众号小灰灰的FPGA,关注可获取相关源码,定期更新有关FPGA的项目以及开源项目源码,包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 2、AXI interconnect互联组件的使用…...
音视频——帧内预测
H264编码(帧内预测) 在帧内预测模式中,预测块P是基于已编码重建块和当前块形成的。对亮度像素而言,P块用于44子块或者1616宏块的相关操作。44亮度子块有9种可选预测模式,独立预测每一个44亮度子块,适用于带有大量细节的图像编码&…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...
第14节 Node.js 全局对象
JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。 在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局…...
