Rust-类型转换进阶

这篇文章收录于Rust 实战专栏。这个专栏中的相关代码来自于我开发的笔记系统。它启动于是2023年的9月14日。相关技术栈目前包括:Rust,Javascript。关注我,我会通过这个项目的开发给大家带来相关实战技术的分享。


关于Rust的类型转换,我在之前的已经感受到了Rust类型的一等公民地位中做了阐述。随着项目进度的推进,对类型转换的使用场景也变得丰富起来。

场景

说到数据转换,在程序开发中是一件很平常的事情,比如,我们下面要讨论的场景
在这里插入图片描述
models::User定义如下:

#[derive(Debug, Deserialize, Serialize)]
pub struct User {pub id: String,pub user_name: String,pub gender: Gender,pub alias: Option<String>,pub birthday_year: Option<u8>,pub birthday_month: Option<u8>,pub birthday_day: Option<u8>,
}

在数据集中,gender的类型是postgres的int not nulltokio_posgres库会将其转换成Rust的i32类型。birthday_year的类型是postgres的int nulltokio_postgres库会自动将其转换成Rust的Option<i32>类型。

因此,我们的目标是

  1. i32转换成models::Gender
  2. Option<i32>转换成Option<u8>

先睹为快,最终的转换应用代码如下

    let row= client.query_one("select id, user_name, alias, gender, birthday_year, birthday_month, birthday_day from users where id=$1", &[id]).await.map_err(MyError::from)?;Ok(User {...gender: SqlGender(row.get("gender")).into(),birthday_year: Sqlu8(row.get("birthday_year")).into(),})

实现步骤

i32 to models::Sex

在这个转换过程中,我们会使用到std::convert::From<T> trait

  1. 声明一个临时类型SqlSex
pub struct SqlGender(pub i32);

之所以要声明这个临时类型,是因为我们要告诉编译器这个tuple接收的数据类型是i32。上面的row.get("gender")的返回实现了FromSql的trait。tokio_postgres通过FromSql实现了对i32的转换。
2. 在models::Gender上实现From<SqlGender>

impl From<SqlGender> for Gender {fn from(val: SqlGender) -> Self {if let Ok(val1) = u8::try_from(val.0) {if let Ok(result) = Gender::try_from(val1) {return result;}}Sex::NotSet}
}

上面的代码,实际上先将i32数据类型转换成u8类型,然后再将u8类型转换成Gender。上面的两个转换过程我们都使用了try_fromtry_from来源于TryFrom trait。其实,如果我们看Rust关于u8的文档,会看见一串From<T>TryFrom<T>的实现。

Option<i32> to Option<u8>

和上面的转不同,这个转换是结果是Option,但由于输入的数据也是一个Option,因此,这里我们还是使用的From<T>。如果转换可能存在失败的情况,且我们要处理失败,那么我们应该使用std::convert::TryFrom<T>

  1. 声明临时类型Sqlu8
pub struct Sqlu8(pub Option<i32>);

声明这个临时类型和上面的原因是一样的,告诉编译器这里使用的是Option<i32>类型。
2. 在Option<u8>上实现From<Sqlu8>

impl From<Sqlu8> for Option<u8> {fn from(val: Sqlu8) -> Self {if let Some(val1) = val.0 {if let Ok(result) = u8::try_from(val1) {return Some(result);}}None}
}

上面的代码先拿到有效的i32数据,然后再将i32转换成u8类型,任何失败都将返回None

转换的应用

实现了上面的步骤,我们通过下面的方式来使用转换。

    let row= client.query_one("select id, user_name, alias, gender, birthday_year, birthday_month, birthday_day from users where id=$1", &[id]).await.map_err(MyError::from)?;Ok(User {...gender: SqlGender(row.get("gender")).into(),birthday_year: Sqlu8(row.get("birthday_year")).into(),})

我们先用声明的临时类型来包裹数据,然后通过调用.into()来实现转换。
Rust本身也有类似的用法,例如将字符串切片转换成String类型。

let msg :String = "hello".into();

这里看起来有没有一点魔幻的感觉,反正我是有的。实现转换的代码和应用转换的代码感觉没啥关联。我查了一下,这是Rust的“关注点分离“设计模式的一种体现。这样设计到好处显而易见,即我们可以无限扩展其类型的转换而不会对已有的代码造成任何影响。例如,我们上面就对i32, u8的转换进行了相关的扩展。

关于临时类型

我们在这里使用临时类型的原因是要告诉编译器,以pub struct Sqlu8(pub Option<i32>);为例,我们要接受一个类型为Option<i32>的值。即相当于一个中间变量。
还有一种情况需要使用临时类型,即如果你要转换的两个类型,都是从第三方模块中引入的,这个时候也需要加入一个临时类型过度。因为Rust不允许转换的两个类型都不在当前模块内。

小结

我们描述了转换的场景,具体的转换步骤和转换的应用方式。这里的场景是数据集和本地类型之间的数据转换。类似的场景还有很多,只要涉及到不同的上下文,数据转换的需求就会出现。使用Rust的std::convert::From<T> trait,实际上就是在实践“关注点分离”的设计模式,它会大大提升我们代码的可维护性和可扩展性,个人认为这是写好Rust代码的重要方法之一。

如有问题,欢迎大家留言交流。关注我,后面会给大家带来更多关于Rust开发实战技术的分享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/162156.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

美国绿氢项目开发商NovoHydrogen完成2000万美元融资

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;总部位于美国科罗拉多州戈尔登的绿氢项目开发商NovoHydrogen今日宣布已完成2000万美元融资。 本轮融资由现代能源公司领投。 该公司打算利用这笔资金进一步扩大其团队&#xff0c;并将其绿氢项目的…

纳米软件科普:开关电源测试方案之如何测试短路保护

开关电源短路保护测试是通过模拟短路状态来检测电源在短路时是否有保护能力&#xff0c;是开关电源一个重要测试项目。通过测试&#xff0c;不仅可以测试开关电源的保护能力&#xff0c;还可以保护电路系统以及对设备的保护&#xff0c;防止受到损坏。那么短路保护要如何测试呢…

Linux创建与删除用户

Linux创建与删除用户 新增用户&#xff1a; adduser 用户名【添加用户】 passwd 用户名【设置用户密码】删除用户&#xff1a; userdel -r 用户名【删除用户】

205、使用消息队列实现 RPC(远程过程调用)模型的 服务器端 和 客户端

目录 ★ RPC模型&#xff08;远程过程调用通信模型&#xff09;▲ 完整过程&#xff1a;代码演示总体流程解释&#xff1a;ConstantUtil 常量工具类ConnectionUtil RabbitMQ连接工具类Server 服务端Client 客户端测试结果服务端客户端 完整代码ConstantUtil 常量工具类Connecti…

文献阅读快速法-ChatPDF

如题&#xff0c;直接提供给大家一款能够快速阅读文档的好工具——iTextMaster。 iTextMaster是一款免费的pdf阅读浏览器&#xff0c;上传pdf文档后等待几秒钟&#xff0c;AI就会自动反馈给用户关于文档的摘要总结。十分的方便且实用。 ChatPDF为您提供简洁的文档摘要。对于那…

plink分析100个性状的批量gwas分析

大家好&#xff0c;我是邓飞。 GWAS分析时&#xff0c;3~5个性状是正常操作&#xff0c;要分析100个性状呢&#xff0c;手动修改参数&#xff0c;工作量是够了&#xff0c;但是程序员的修养体现在哪里了&#xff1f;&#xff1f;&#xff1f; 如果还是按照每个性状一个文件夹…

2023年中国液晶电视出口现状、品牌格局及行业发展趋势[图]

液晶电视指采用液晶显示面板的电视机&#xff0c;是目前最主流的彩色电视机&#xff0c;主要结构包括液晶面板模组、电子线路模块、结构件等。 目前常用的液晶电视有STN-LCD&#xff08;SuperTN-LCD&#xff0c;超扭曲向列LCD&#xff09;、DSTN-LCD&#xff08;DoublelayerSTN…

百度发布全新 AI 互动式搜索:百度简单搜索

本心、输入输出、结果 文章目录 百度发布全新 AI 互动式搜索&#xff1a;百度简单搜索前言主要能力 相关资料能力介绍 百度搜索升级发文告用户如何获取百度简单搜索百度简单搜索的定位百度简单搜索在 APP 上面的体验讨论和点评我们关注的几个问题 弘扬爱国精神 百度发布全新 AI…

Netty系列教程之NIO基础知识

近30集的孙哥视频课程&#xff0c;看完一集整理一集来的&#xff0c;内容有点多&#xff0c;请大家放心食用~ 1. 网络通讯的演变 1.1 多线程版网络通讯 在传统的开发模式中&#xff0c;客户端发起一个 HTTP 请求的过程就是建立一个 socket 通信的过程&#xff0c;服务端在建立…

机器学习,神经网络中,自注意力跟卷积神经网络之间有什么样的差异或者关联?

如图 6.38a 所示&#xff0c;如果用自注意力来处理一张图像&#xff0c;假设红色框内的“1”是要考虑的像素&#xff0c;它会产生查询&#xff0c;其他像素产生 图 6.37 使用自注意力处理图像 键。在做内积的时候&#xff0c;考虑的不是一个小的范围&#xff0c;而是整张图像的…

代码的艺术-Writing Code Like a Pianist | 京东云技术团队

前言 如何评定一个系统的质量&#xff1f;什么样的系统或者软件可以称之为高质量&#xff1f;可以从三个角度来看&#xff0c;一是架构设计&#xff0c;例如技术选型、分布式系统中的数据一致性考虑等&#xff0c;二是项目管理&#xff0c;无论是敏捷开发还是瀑布式开发&#…

【SpringCloud微服务项目实战-mall4cloud项目(4)】——mall4cloud-rbac

mall4cloud-rbac角色权限访问控制模块 系统架构与模块介绍系统架构rbac模型介绍 相关代码权限校验接口代码 补充 代码地址 github地址 fork自github原始项目 gitee地址 fork自gitee原始项目 系统架构与模块介绍 系统架构 从图中可以看到&#xff0c;微服务集群中&#xff0c;…

基于Qt QSlider滑动条小项目

QSlider 是滑动条控件,滑动条可以在一个范围内拖动,并将其位置转换为整数 1. 属性和方法 QSlider 继承自 QAbstractSlider,它的绝大多数属性都是从 QAbstractSlider 继承而来的。 2.QSlider信号 - `valueChanged(int value)`: 当滑块的值改变时发出信号,传递当前滑块的值…

基于SVM+Webdriver的智能NBA常规赛与季后赛结果预测系统——机器学习算法应用(含python、ipynb工程源码)+所有数据集(三)

目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理2. 特征提取3. 模型训练及评估1&#xff09;常规赛预测模型2&#xff09;季后赛模型创建 4. 模型训练准确率 相关其它博客工程源代码下载其它资料下载 前言 本项目使用了从NBA官方网站获得的数据&…

JOSEF约瑟 漏电继电器 JHOK-ZBG1 φ25mm AC220V 0.1A/0.1S 分体式

系列型号 JHOK-ZBG1 φ25mm漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBG2 φ25mm漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBG1 φ45mm漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBG2 φ45mm 漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBG1 φ100mm漏电&a…

猜数字游戏(Rust实现)

文章目录 游戏说明游戏效果展示游戏代码游戏代码详解生成神秘数字读取用户输入解析用户输入进行猜测比较 游戏说明 游戏说明 游戏运行逻辑如下&#xff1a; 随机生成一个1-100的数字作为神秘数字&#xff0c;并提示玩家进行猜测。如果玩家猜测的数字小于神秘数字&#xff0c;则…

初始web项目tomcat部署报错404

问题 简单地创建了一个web项目&#xff0c;结果一运行就404咧&#xff0c;真滴烦。。。接下来的项目也没法继续了 问题原因&#xff1a;缺少文件 其实造成这样问题的原因有不少&#xff0c;但在这里我是踩了一个坑。在出问题之前&#xff0c;我运行的其他项目都是可以跑的&…

2. 验证1101序列(Mealy)

题目要求&#xff1a; 用 M e a l y \rm Mealy Mealy型状态机验证 1101 1101 1101序列 题目描述&#xff1a; 使用状态机验证 1101 1101 1101序列&#xff0c;注意&#xff1a;允许重复子序列。 方法一&#xff1a; 去掉 M o o r e \rm Moore Moore的 s 4 s_4 s4​&#xff…

掌握.NET基础知识(一)

前言 本文将讲解一些.NET基础。NET基础是指在计算机编程中使用.NET框架所需要的基础知识..NET的认识: .NET是由微软开发的一个跨平台的应用程序开发框架。它包括一个运行时环境和一个面向对象的程序库&#xff0c;可以用于开发各种类型的应用程序&#xff0c;包括桌面应用程序、…

数据驱动娱乐的未来:揭秘爱奇艺如何利用Apache Spark实现个性化推荐和内容分析

Apache Spark 在爱奇艺的现状与应用 Apache Spark 是爱奇艺大数据平台的核心组件&#xff0c;被广泛应用于数据处理、数据同步和数据查询分析等关键场景。在数据处理方面&#xff0c;爱奇艺通过数据开发平台支持开发者提交 Spark Jar 包任务或 Spark SQL 任务&#xff0c;进行…