舍弃Java模式,从头开始,用Rust书写编程的未来

news2025/1/10 0:03:58

沉迷于Rust之美:类型安全、内存安全、注重正确性,这叫人如何不爱呢?

在开发Apollo(一款Python应用)时,遇到了许多错误。如果我使用Rust,大多数错误都能被编译器捕获(虽然无法做到百分之百,但比例应该非常高)。一般来说,编译器可以捕获许多问题,而使用动态语言(如Python或Ruby)时,这些问题有可能进入生产环境。尽管并非所有编译器都能做到这一点,但Rust强调正确性,这正是最吸引我的地方。

我在工作中编写了大量 Java 代码。虽然 Java 不是我最喜欢的语言,但它的编译时检查很强大。在进行重大重构时,Java 没有使用 Python 或Ruby 那么可怕。有了这样的编译器,遇到不正确或遗漏的导入语句,程序在运行时就会停止。虽然我们通常会通过测试来发现这些问题,但是将这些检查融入到语言中还是很有必要的。

然而 Java 编译器并不完美。它无法防止许多种错误,其中最令人头疼的就是空引用。在Java 中几乎所有东西都可以为 ,相关的错误直到运行时你才能发现。与之相反,Rust 拥有适当的结构来引导你处理未知值。当然,你可以选择忽略此类提示,但编译器会强制你做出深思熟虑的决定。

那么,Rust 是否比 Java 更好呢?Rust确实有许多让我很喜欢的地方。Rust 的承诺对我来说非常有吸引力。但我的 Rust 之旅并不全是阳光和彩虹。尽管 Rust 与 Java 有相似之处,但二者并不一样。直到停止按照 Java 的方式编写 Rust,我才发现了编写 Rust 代码的乐趣。

一切必须是接口

对于 Java 开发人员(我就是这样的开发人员)来说,一切都是接口,虽然这个说法不完全准确,但也有一定的道理。Java 中的接口使用起来很有趣。应用程序由小的工作单元组成,每个工作单元都不了解另一个工作单元的内部工作原理。建立这样的依赖关系树需要在前提付出不少努力,但一旦完成,就能拥有一支独立服务的大军供你使用。

然而,Rust 中没有接口,有的是特征(trait)。这些特征在很多方面与 Java 中的接口很相似。然而,我们不应该将 Rust 中的一切都写成特征。记住,Rust 的内存安全是一个很强大的功能。而代价是无法轻松“注入”实现特征的代码。

f2f6d0e7ede32e50da13208af03a43af.jpeg

上面的代码无法编译,因为编译时无法确定 Named 的大小。为了解决这个问题,我们可以将这个特征放入Box ,这样我们就可以指向堆上动态分配的内存(称为 trait 对象)。Box 本身的大小已知,因此程序就可以编译了。

7516380373089362c13e30c026765237.jpeg

Box不太方便使用,因此我不太喜欢这种模式。我会尽可能避开它们。我们可以使用泛型来指定 特征类型。

这两种方式有何不同?初看之下结果是一样的。实际上二者的差异在于动态调度与静态调度。对于特征对象,具体的类型是在运行时解析的,而泛型的具体类型是在编译时解析的。

实际上,这意味着只要我们可以在编译时推断所有类型,就可以不使用泛型。如果直到运行时才能推断类型,则必须使用 Box。

所有权

所有权的问题依然存在。如果上述 Named 特征是应用程序中其他服务的必需依赖项,该怎么办?我们是否需要创建一个主Named ,然后将 &Named 传递给每个依赖项,这样就会引入生命周期?

8d5b4581233a5ee1ef9e9a3ae99c41f2.jpeg

还是说我们应该使用 Arc,这样依赖服务就可以写为 Arc<Box<dyn Named>>,从而允许并发访问所拥有的资源?

8a811af2a81a49353180d12c5bc7df53.jpeg

两种方法我都尝试过了,虽然可行,但都不太理想,尤其是当应用程序中的每项服务都受到影响时。

纯函数

将 Rust 当成纯粹的面向对象语言并不合适。虽然我仍然像上面的例子一样编写“服务对象”,但只在必要时使用它们,实际上我更推荐纯函数。

我们来考虑一个处理结账事件的函数,该函数会更新系统中的客户 ID。

ad0f62fdfc289a6f34274107a5292b04.jpeg

虽然我们可以将这段处理编写为一个服务,其中的 UserRepo 是一个注入值,但上面我们已经探讨过了,这样做会带来一定的复杂性。此外,我们仍然可以轻松注入 UserRepo 的不同实现,例如提供不会访问生产数据库的实现,因此也没有理由将其编写为服务。缺点在于,我们的函数签名可能会有点“繁忙”,不过这种程度的“痛苦”根本不算什么。

拥抱真正的 Rust

以前我深陷“Rust 语言很难”的误区不能自拔。一个重要原因是我坚持按照其他语言的方式编写 Rust 代码。虽然汲取以往的经验很重要,但拥抱 Rust 本身的惯用写法对于掌握这门语言也很重要。只有转变心态才能真正掌握 Rust。按照不适合的方式编写 Rust 会让我们陷入苦苦的挣扎,我们应该拥抱它本来的样子。


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ubuntu联网图标消失

sudo service NetworkManager stopsudo rm /var/lib/NetworkManager/NetworkManager.statesudo service NetworkManager start执行 sudo rm /var/lib/NetworkManager/NetworkManager.state 命令将删除位于 /var/lib/NetworkManager 目录下的 NetworkManager.state 文件。

(C语言进阶)笔试题详解

一.要点回顾 1.一维整形数组 (1)sizeof()对一维整形数组的应用 #include<stdio.h> int main() {int a[] {1,2,3,4};printf("%d\n", sizeof(a));//16 //sizeof(数组名),数组名表示整个数组&#xff0c;计算的是整个数组的大小&#xff0c;单位是字节printf…

微信小程序备案流程操作详解

1、2023年9月1号小程序开始必须备案了,各位小程序商城只需要按流程自主去微信小程序后台操作即可; 2、对未上架的微信小程序,从2023年9月1号开始需先备案才能上架; 3、对存量已上架的小程序,需在2024年3月31号前完成备案即可。逾期未完成备案,平台将按照备案相关规定于…

英语学习工具推荐

无论您是初学者还是想要巩固英语能力的学习者&#xff0c;我们都为您提供了一个高效而便捷的英语学习工具。 英语复读机&#xff0c;您可以随时输入您想要复读的英语单词、句子或者文章。我们的复读机会循环播放您输入的内容&#xff0c;帮助您加深记忆、提高听力和口语表达能力…

相似性搜索:第 2 部分:产品量化

系列文章前篇&#xff1a;相似性搜索&#xff1a;第 1 部分- kNN 和倒置文件索引_无水先生的博客-CSDN博客 SImilarity 搜索是一个问题&#xff0c;给定一个查询的目标是在所有数据库文档中找到与其最相似的文档。 一、介绍 在数据科学中&#xff0c;相似性搜索经常出现在NLP领…

模式匹配(数据结构)

朴素模式匹配算法 #include <stdlib.h> #include <iostream> #include <stdio.h> #define MaxSize 255typedef struct{char ch[MaxSize];int length; }SString;//初始化 SString InitStr(SString &S){S.length0;return S; } //给串赋值 SString SetStr…

【计算机毕设选题推荐】产品管理系统SpringBoot+SSM+Vue

前言&#xff1a;我是IT源码社&#xff0c;从事计算机开发行业数年&#xff0c;专注Java领域&#xff0c;专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务 项目名 基于SpringBoot和SSM的产品管理系统 技术栈 SpringBootSSMVueMySQLMaven 文章目录 一、产品…

pip 安装dgl的问题

在该官网链接找到需要的对应包&#xff1a; 官网链接 安装之后可能的问题&#xff1a; 这个时候应该是网络问题导致的&#xff0c;这个时候可以自行前往网站下载 下载之后安装&#xff1a; 发现缺少依赖 p s u t i l psutil psutil&#xff0c;于是前往官网下载&#xff1a;…

C语言数据类型详解

1、什么是数据类型&#xff1f; 计算机编程语言是用来控制计算机的行为及操作&#xff0c;协助人们解决现实中的问题&#xff0c;其能表达的数据类型也是从实际中提取并抽象出来形成的数据结构描述。 例如&#xff1a;数学中数的基础分类有正整数、负整数、小数等类别&#x…

Linux系统编程:makefile以及文件系统编程

增量编译概念 首先回顾一下我们之前写的各种gcc指令用来执行程序&#xff1a; 可以看见非常繁琐&#xff0c;两个文件就要写这么多&#xff0c;那要是成百上千岂不完蛋。 所以为了简化工作量&#xff0c;很自然的想到了将这些命令放在一起使用脚本文件来一键执行&#xff0c…

Python+requests+Excel数据驱动的接口自动化测试中解决接口间数据依赖

在实际的测试工作中&#xff0c;在做接口自动化过程中往往会遇到接口间数据依赖问题&#xff0c;即API_03的请求参数来源与API_02的响应数据&#xff0c;API_02的请求参数又来源与API_01的响应数据&#xff0c;因此通过自动化方式测试API_03接口时&#xff0c;需要预先请求API_…

Linux下将驱动编译进内核

在开发的过程中&#xff0c;一般都是将驱动编译成模块&#xff0c;然后将其发送到开发板加载驱动进行功能验证&#xff0c;驱动的功能验证没有问题后就可以将其编译进内核了。本文将介绍如何把上一篇文章Linux下设备树、pinctrl和gpio子系统、LED灯驱动实验中的LED驱动编译到内…

[题] 前缀和 (含输入输出的耗时对比)

题目 前缀和 题解 前缀和模板 太简单了就多加了点东西:对比cin cout和scanf printf的耗时对比 代码 #include <iostream> using namespace std; const int N 100010; int n, m; int a[N], s[N]; int main(){scanf("%d%d", &n, &m);//原数组 for (in…

CentOS 挂载新磁盘以及磁盘扩容操作教程

1.搭载新加磁盘 # 查看磁盘 fdisk -l #新盘&#xff08;/dev/sdb&#xff09;创建分区 #虚拟机 fdisk /dev/sdb #阿里云 fdisk /dev/vdb #创建/dev/sdb1为新的PV&#xff08;物理卷&#xff09; 【创建物理卷命令】 #虚拟机 pvcreate /dev/sdb1 #阿里云 pvcreate /dev/vdb1 查…

Air001 ADC内部输入通道温度传感器读取

Air001 ADC内部输入通道温度传感器读取 &#x1f4cb;Air001 内部集成的温度传感器说明 &#x1f58d;温度传感器产生一个随温度线性变化的电压。温度传感器在内部被连接到ADC内部的输入通道上&#xff0c;用于将传感器的输出转换成数字数值。 &#x1f4d3;Air001模拟/ 数字转…

CANdb++数据库操作

CANdb数据库操作 创建工程结构文件夹新建数据库&总线描述节点设置节点创建配置Message属性信号设置节点收发信号 环境变量配置一致性检验数据库工程XVehicle.dbc导入工程文件总结 创建工程结构文件夹 在文件夹X-Vehicle-1下&#xff0c;建立工程目录文件夹CANdb&#xff0…

优雅而高效的JavaScript——模板字面量

&#x1f928;博主&#xff1a;小猫娃来啦 &#x1f928;文章核心&#xff1a;优雅而高效的JavaScript——模板字面量 文章目录 什么是模板字面量使用模板字面量插入变量处理多文本模板字面量的高级应用标签模板字量自定义模板字面量函数 常见应用场景拼接字符串HTML模板SQL查询…

【LeetCode热题100】--347.前K个高频元素

347.前K个高频元素 方法&#xff1a;堆 首先遍历整个数组&#xff0c;并使用哈希表记录每个数字出现的次数&#xff0c;并形成一个「出现次数数组」。找出原数组的前 k 个高频元素&#xff0c;就相当于找出「出现次数数组」的前 k 大的值 利用堆的思想&#xff1a;建立一个小…

tomcat多实例部署jenkins

tomcat多实例部署jenkins 文章目录 tomcat多实例部署jenkins1.简介&#xff1a;2.优缺点&#xff1a;3.工作原理&#xff1a;4.工作流程&#xff1a;5.tomcat多实例部署jenkins流程5.1.环境说明5.2.部署前准备工作5.3.多实例部署tomcat5.4.部署jenkins5.5.创建一个jenkins项目5…

乐高Studio打开Solidworks零件/装配体 (sw另存obj文件)

solidworks 2020 Lego studio / part designer 截至2023-10-13&#x1f382;最新版 文章目录 操作步骤1&#xff09; solidworks 开启 ScanTo3D 功能2&#xff09; 零件 / 装配体 保存至stl格式文件3&#xff09; 以SanTo3D网格文件方式打开stl4&#xff09; 将打开的stl另存为…