我作为TypeScript开发人员是如何学习Rust的

news2024/10/21 11:39:15

讲讲我作为TypeScript开发人员学习Rust的经验吧,希望对你有帮助

像许多开发人员一样,我通过专注于网络技术开始了我的编程生涯。我相信这是一个很好的起点,JavaScript,互联网的语言,以及许多,是一个令人难以置信的多才多艺的选择。

随着我对JavaScript等高级语言的经验越来越丰富,我也对它们的工作原理越来越感兴趣:它们正在做出哪些选择和权衡,以及更高层次的抽象的好处和成本是什么。

对我来说,更深入理解的最好方法之一是学习低级编程语言。毕竟,这些是通常解析和解释我们的JavaScript代码的语言。例如,V8引擎(由Google Chrome和Node.js使用)和WebKit(由Safari和Bun使用)都是用C++编写的。但是,尽管C++是低级编程的中流砥柱,但C++不是我选择的语言......

在伟大的低级编程语言中,Rust对我来说是最令人兴奋的。去年,Rust连续第八年成为Stack Overflow年度调查中最受赞赏的编程语言。

该语言承诺在与C和C++相同的联盟中运行时性能,但具有严格的类型系统、许多内存安全功能和更主动的错误处理方法——因此您可以避免垃圾收集器的开销,避免内存泄漏的风险,而内存泄漏在C等语言中更容易创建。

Rust用途广泛,具有面向对象和函数式编程的范式,连续第三年,它一直是Web汇编中最受欢迎的语言,甚至已成为Linux内核中的重要语言。Rust也在JavaScript领域掀起波澜,在那里它一直被用来构建重要项目,如Deno,以及最近的LLRT(亚马逊无服务器函数的低延迟运行时)。

如何学习Rust

与任何其他编程语言一样,我认为学习Rust的最佳方式是尝试用该语言编程一些东西。

然而,Rust的初始学习曲线似乎比我近年来尝试过的其他语言更陡峭,所以在开始使用该语言之前,值得花更长的时间浏览入门材料。

Rust组织的网站有很好的建议。现在,这些是The Book、Rustlings课程和Rust by Example。我还推荐Rust by Practice,这是一个类似于Rustlings的互动课程。

在YouTube上,NoBoilerplate频道帮助我对这种语言感到兴奋,并且是解释一般Rust概念的绝佳来源。如果您对托管Rust感兴趣,AWS有一篇关于在其平台上增加对Rust支持的博客文章。

本文的其余部分不是Rust的初学者指南。如果这就是你要找的,我建议你点击上面的链接。相反,与我每天专业使用的语言TypeScript相比,我分享了开发人员使用Rust体验的一些最显著差异的想法。

编译器

Rust编译器经常被引用为Rust最好的部分之一,然而,对于初学者来说,它也可能感觉是最令人讨厌的部分之一!

来自TypeScript,我惊讶于编译器在多大程度上改变了编码体验。像许多开发人员一样,我通常会避开适当的调试工具,而倾向于自由记录值。但在Rust中,只有当编译器满意时,您才能记录值。

在某些情况下,这被证明是令人沮丧的:例如,在为反序列化步骤编写严格类型之前,我想记录一个请求的JSON有效负载。(后来,我了解到这可以用theserdeserde_json::Value类型来完成)。

但一般来说,努力满足编译器意味着,通常,当我运行代码时,它会按照我的预期工作。这里的权衡似乎很清楚。至少对于初学者来说,运行代码确实需要更长的时间,但当该代码确实运行时,它更安全、更可预测、性能更高。你在写作阶段投入了更多的工作,但出现错误或性能记忆问题的几率似乎更低——在大型、不断增长的项目中,这些好处感觉越来越重要。

来自错误消息不太有用的语言的开发人员可能会发现,他们已经准备好快速扫描错误。但到目前为止,我发现Rust编译器错误非常好,经常确切地告诉你需要做什么才能运行代码——我对语言及其类型越有经验,我就越能理解编译器试图告诉我什么!

类型系统

我知道不是每个JavaScript开发人员都喜欢TypeScript——例如,请参阅这篇(不)著名的博客文章——但我无法想象在没有类型的情况下编写大型JavaScript应用程序。然而,TypeScript有其弱点,我认识到拥有一种类型为一流公民的语言有很多好处。Rust的类型系统经常被誉为其最佳功能之一。

也就是说,Rust的类型系统对我来说是新的部分不是Rust独有的,而是几乎所有低级语言的特征。例如,像其他低级语言一样,Rust允许我们非常具体地说明我们希望变量占用多少内存空间。如果我们知道一个数值将始终是0到255之间的整数,我们可以将其分配给长度为8位的u8。或者,如果我们的数字可以高于255,但我们知道是否会低于65,535,那么我们可以将其分配给16位u16类型,等等。

然而,在某些方面,Rust确实比其他低级语言走得更远。例如,它提供了至少八种字符串类型,而不是C的一个char[]类型,这有助于我们避免脚枪。(尽管如此,不要害怕,因为大多数用例都由&str和String覆盖!)

当然,TypeScript没有提供接近这种粒度水平的地方,因为根据设计,JavaScript不希望我们担心内存管理,因此为我们分配内存。这为我们节省了一份工作,但效率较低,因为JavaScript引擎必须在程序运行时动态分配内存。在小规模上,这没有什么区别。但在大型应用程序中,更高效和有目的的内存分配可以使程序占用更少的内存占用空间。

内存分配

在TypeScript中,我们在Javascript(一种不读取我们类型的语言)之上叠加类型注释,每当构建TypeScript代码时,它们都会被删除。

在Rust中,与其他类型为一流公民的语言一样,类型注释不仅仅是注释,它为该特定类型分配内存,并向我们保证该值将具有给定类型。

例如,如果我们将i8类型传递给下面的parse方法,它为small_int保留了8位内存。

 
 

let small_int = "127".parse::<i8>().unwrap();

parse方法甚至可以从变量类型中推断类型,因此我们也可以编写:

 
 

let small_int: i8 = "127".parse().unwrap();

在这种情况下,如果我们试图超越给定类型允许的内存,编译器也会对我们大喊大叫。因此,如果我们尝试将字符串"128"解析为i8,我们将无法编译。

比较TypeScript,其中类型标记只是标记。它们不会更改底层类型或分配的内存。下面,TypeScript期望x是一个字符串。但在底层的JavaScript中,它将是一个数字。

 
 

const x = 10 像字符串一样未知;

这个例子对TypeScript编译器有点不公平;我们正在使用unknown作为转义舱口来强行分配错误的类型!

然而,这是一个很容易抓住的简单例子。在现实世界的应用程序中,当处理更复杂的数据类型或从第三方获取的数据时,TypeScript更容易歪曲现实。

错误处理

让我们再次以将字符串转换为整数为例。这一次,让我们想象一下我们的整数是由用户提供的字符串,因此我们无法再保证我们可以正确解析它。

 
 

let parsed_int = submitted_str.parse::<i32>().unwrap();

在这里,我们使用unwrap来获得成功解析的值。但这种方法通常不鼓励。相反,Rust为我们提供了Result枚举,这迫使我们手动处理错误。

We can still cause our program to panic with thepanic!macro, but we can pass a custom error message which will help us quickly understand what went wrong:

添加图片注释,不超过 140 字(可选)

或者我们可以返回一个默认值——在这种情况下是0:

添加图片注释,不超过 140 字(可选)

还有一个简写方法:unwrap_or_default。

当然,这种行为在JavaScript中是可能的,但区别在于,在JavaScript中,您必须选择加入,而在Rust中,您必须使用unwrap来选择退出。

或者,换句话说,在JavaScript中,你必须有意识地处理错误。而在Rust中,你被迫要么处理错误,要么有意识地决定你只关心成功的道路。

可选值

Rust使用类似的方法来处理可选值。在TypeScript中,我们可以使用方便的?指示一个值可能undefined。

添加图片注释,不超过 140 字(可选)

这个TypeScript代码将毫无问题地编译,即使我们有返回我们不想要的东西的风险!

但是,如果我们使用Option在Rust中编写类似的东西,我们会收到一个编译时错误。

添加图片注释,不超过 140 字(可选)

The code above warns us that we cannot useOptioninside ourformat!macro — preventing us from returning something unexpected. Instead, we are forced to handle this possibility. Here’s one solution, usingmatch:

添加图片注释,不超过 140 字(可选)

再一次,这在TypeScript中是可以实现的——而且它更简洁。但两种语言之间的关键区别在于,在TypeScript中,开发人员有需要识别潜在的问题,因此我们最终不会返回"Hello undefined"但在Rust中,除非我们处理名称不可用的情况,否则我们的代码将无法编译。

在这样的简单例子中,很难认识到更冗长的方法的好处,因为很容易看出可能会出错什么。但是,如果您曾经开发过大型应用程序,很明显,Rust的选择退出方法可以使我们免于许多潜在的事故。

所有权和借贷

最后,我想谈谈所有权和借贷,这些概念在像Rust这样的低级语言中比像TypeScript这样的高级语言更有意义。

在TypeScript中,我们需要意识到我们是突变值还是克隆值。

添加图片注释,不超过 140 字(可选)

在上面的TypeScript代码中,sort将数组原位突变,更改原始值。但toSorted创建一个克隆,我们可以将其分配给一个新的变量,并保持原始数组不变。

一般来说,像toSorted这样的非破坏性方法在TypeScript等语言中通常是首选,因为跟踪突变变量可能很棘手,除非对内存或性能有明显的好处,否则通常认为最好完全避免这样做。

然而,Rust允许我们更深入地了解突变或克隆值,其好处是,一旦值实现其光荣的目的,我们可以更有效地使用内存,也可以更轻松地释放内存。

首先,默认情况下,所有变量都是不可变的,并且必须使用mut关键字明确标记为可变。

此代码抛出一个错误:

 
 

让foo = 10; foo += 10;

此代码不:

 
 

让mut foo = 10; foo += 10;

这感觉大致等同于JavaScript中的let与const。胸围锈走得更远。

例如,在JavaScript中,某些变量类型,如数组,总是可变的。即使我们使用const实例化它们,我们也可以push、pop和重新分配索引。在Rust中,我们需要mut才能做到这一点:

 
 

let mut nums: Vec<i32> = vec![1,2,3,4,5]; nums.push(6);

Rust还允许我们将值的所有权从一个变量转移到另一个变量。以以下为例:

 
 

让nums:Vec<i32> = vec![1,2,3,4,5]; let doubles: Vec<i32> = nums.into_iter().map(|n| n * 2).collect(); dbg!(nums); // 这个抛出 dbg!(双打);

此代码抛出,因为intointo_iter方法创建了一个“消耗迭代器”;换句话说,从nums夺走所有权,并赋予它todoubles。因此,我们不能调用dbg!(nums)在doubles创建后。

如果我们想保持对nums访问权限,而是克隆其值,我们可以使用iter方法而不是into_iter。重要的是,Rust给了我们一个选择,转移所有权的能力可以帮助我们提高内存分配的效率。

We can also move simple values. In the code below, when our str variable is used as an argument for calculate_length , it is no longer accessible.

 
 

fn main() { let str = String::from("Hello world!"); let len = calculate_length(str); dbg!(str); // 这扔 } fn calculate_length(s: String) -> usize { s.len() }

在这里,我们可以通过使用ampersand&传递对我们字符串的引用来解决这个问题,而不是传递字符串本身。我们还需要更新函数参数才能获得引用:

 
 

fn main() { let str = String::from("hello"); let len = calculate_length(&str); dbg!(str,len); } fn calculate_length(s: &String) -> usize { s.len() }

要反其道而行之,并取消引用一个值,我们可以使用星号*。这些功能共同帮助我们安全高效地控制内存,正因为如此,Rust不需要依赖垃圾收集器,这使我们能够解锁更高的性能水平,而没有C等语言的风险,这使开发人员有更大的风险来了解他们在做什么!

总的来说,我学习和使用Rust的早期经验是非常积极的。入门感觉比我近年来尝试过的其他语言更困难,但我相信学习Rust已经让我更加了解我每天使用的高级语言的基本工作,我很高兴能在个人项目中更多地使用它。

如果您是Rust的新手或对学习这种语言感到好奇——特别是来自更高层次的语言——那么希望您觉得这篇文章有用。当然,这只是一个粗略的观点,有很多主题,如特征和寿命,超出了文章的范围。

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

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

相关文章

Axure原型设计秘籍:解锁高效设计与开发的宝藏工具

​ 在快速迭代的数字时代&#xff0c;原型设计成为了产品开发与用户体验优化的关键环节。Axure&#xff0c;作为一款备受推崇的原型设计工具&#xff0c;凭借其强大的功能、直观的界面和丰富的资源&#xff0c;成为了设计师和产品经理们的得力助手。本文将带你深入探索Axure的原…

JavaScript中的对象,常用内置对象和数据类型

一、对象 1.概念 什么是对象&#xff1f; 在JavaScript中&#xff0c;对象是一组无序的相关属性和方法集合&#xff0c;所有的事物都是对象&#xff0c;例如&#xff1a;字符串、数值、数组和函数等等。 对象是由属性和方法组成的。 属性&#xff1a;事物的特征&#xff0c;在…

使用CSS Flexbox创建简洁时间轴

使用CSS Flexbox创建简洁时间轴 在网页设计中,时间轴是一种常见且有效的方式来展示事件的顺序和进程。本文将介绍如何使用CSS Flexbox创建一个简洁优雅的时间轴,无需复杂的JavaScript代码。 基本HTML结构 首先,我们需要创建基本的HTML结构: html复制<div class"ti…

《CUDA编程》8.共享内存的合理使用

共享内存是 一种可被程序员直接操控的缓存&#xff0c;主要作用有两个&#xff1a; ①减少核函数中对全局内存的访 问次数&#xff0c;实现高效的线程块内部的通信 ②提高全局内存访问的合并度 将通过两个具体的例子阐明共享内存的合理使用&#xff0c;一个数组归约的例子和讨矩…

深入解析“低代码平台”与“零代码平台”:区别与应用场景

随着企业数字化转型的加速&#xff0c;低代码平台与零代码平台作为提升开发效率、降低IT成本的有效工具&#xff0c;正逐渐成为企业软件开发的新趋势。这两种平台虽然都旨在简化应用开发过程&#xff0c;但在功能、适用场景及用户群体上存在着显著差异。 低代码平台&#xff1a…

如何通过Chrome设置保护你的在线隐私

在当今数字时代&#xff0c;保护个人隐私和在线安全变得尤为重要。谷歌浏览器作为全球最受欢迎的网络浏览器之一&#xff0c;提供了多种功能来帮助用户保护自己的在线隐私。本教程将指导你如何通过谷歌浏览器设置来提高你的在线隐私保护水平。&#xff08;本文由https://www.li…

highcharts样式记录

图表设置 const rendChart (min, max) > {Highcharts.setOptions({global: { useUTC: false },});Highcharts.chart(hourly-chart, {chart: {spacingBottom: 0,marginLeft: 53,marginTop: 10,marginBottom: 0,marginRight: 13,style: {fontSize: 0.2rem,color: #363a44,li…

论文笔记 ICLR 2024 MogaNet: Multi-Order Gated Aggregation Network

配图中有2个分支&#xff0c;一个是subtract的输出和缩放因子&#xff08;γs&#xff09;相乘之后的结果&#xff0c;另一个是11卷积输出的结果&#xff0c;这两个分支的输出进行element-wise addition&#xff0c;这两个分支的输出分别代表什么&#xff1f; 为什么”增强局部…

1486. 数组异或操作

1486. 数组异或操作 题目含义&#xff1a;根据整数 n n n 和 s t a r t start start 构造一个数组&#xff0c;数组元素为 n u m s [ i ] 2 i s t a r t , i ∈ [ 0 , n − 1 ] nums[i] 2i start, i \in [0,n-1] nums[i]2istart,i∈[0,n−1]&#xff1b;最后返回这个数组…

电脑 WiFi 上网,开发板和电脑直连,如何才能让开发板也有网络

目录 问题 解决方法 1.设置电脑为WLAN共享模式 2、设置以太网IP 3、设置开发板IP及网关 4、测试 5、开发板重启之后会自动清空 /etc/resolv.conf文件中的内容问题解决 问题 电脑 WiFi 上网&#xff0c;开发板和电脑直连,如何才能让开发板也有网络 解决方法 1.设置电脑…

父子情深!汤姆克鲁斯已经结束英国的奢华生活搬回美国跟儿子团聚

汤姆克鲁斯似乎一直专注于在英国的奢华生活方式。过去五年里&#xff0c;他拍摄了许多电影&#xff0c;还被看到与皇室成员和一线明星一起参加派对。但消息人士称&#xff0c;他可能正在准备搬回美国&#xff0c;以便更接近他的儿子康纳。 在跨过大西洋的五年后&#xff0c;他…

使用electron+vue开发桌面应用

electron是什么 electron由Node.jsChromiumNative APIs构成。你可以理解成&#xff0c;它是一个得到了Node.js和基于不同平台的Native APIs加强的Chromium浏览器&#xff0c;可以用来开发跨平台的桌面级应用。 它的开发主要涉及到两个进程的协作——Main&#xff08;主&#x…

力扣题解(鸡蛋掉落)

887. 鸡蛋掉落 已解答 困难 相关标签 相关企业 给你 k 枚相同的鸡蛋&#xff0c;并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑。 已知存在楼层 f &#xff0c;满足 0 < f < n &#xff0c;任何从 高于 f 的楼层落下的鸡蛋都会碎&#xff0c;从 f 楼层或比它…

JVM可视化监控

1 JConsole 一、介绍 JConsole 是一种 Java 监控和管理控制台工具&#xff0c;可以用于监视 Java 虚拟机&#xff08;JVM&#xff09;的性能和资源利用情况。它提供了一种图形化界面&#xff0c;可以实时查看 JVM 的运行状态、内存使用情况、线程活动、垃圾回收等信息&#xf…

Spring 实现 3 种异步流式接口,干掉接口超时烦恼

大家好&#xff0c;我是小富&#xff5e; 如何处理比较耗时的接口&#xff1f; 这题我熟&#xff0c;直接上异步接口&#xff0c;使用 Callable、WebAsyncTask 和 DeferredResult、CompletableFuture等均可实现。 但这些方法有局限性&#xff0c;处理结果仅返回单个值。在某…

每日OJ题_牛客_小乐乐改数字_模拟_C++_Java

目录 牛客_小乐乐改数字_模拟 题目解析 C代码 Java代码 牛客_小乐乐改数字_模拟 小乐乐改数字_牛客题霸_牛客网 (nowcoder.com) 描述&#xff1a; 小乐乐喜欢数字&#xff0c;尤其喜欢0和1。他现在得到了一个数&#xff0c;想把每位的数变成0或1。如果某一位是奇数&#…

Python 工具库每日推荐【PyAutoGUI】

文章目录 引言Python桌面自动化库的重要性今日推荐:PyAutoGUI工具库主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例案例:自动化图像识别和点击案例分析高级特性失败安全机制相对坐标操作扩展阅读与资源优缺点分析优点:缺点:总结【 已更新完 Python工…

如何远程查看孩子的电脑使用?

越来越多的家庭拥有了多台电脑和智能设备。家长们往往没有办法时刻陪伴在孩子身边&#xff0c;监督他们的上网行为。而远程控制电脑可以帮助家长在任何时间、任何地点对孩子的电脑进行监控和管理&#xff0c;确保他们能够安全、健康地使用互联网。 通过远程控制软件&#xff0c…

锦锐科技CA51F7系列笔记

1、PWM &#xff08;1&#xff09;芯片一共有6个PWM通道&#xff08;PWM0~PWM5&#xff09; &#xff08;2&#xff09;IRCH时钟&#xff08;IRCH 频率为 16MHz&#xff09; &#xff08;3&#xff09;IRCL时钟&#xff08;IRCL频率为100KHz&#xff09; &#xff08;4&…

JavaScript 命令模式实战:打造可撤销的操作命令

一. 前言 在前端开发中&#xff0c;命令模式&#xff08;Command Pattern&#xff09;作为一种行为型设计模式&#xff0c;可以帮助我们将请求封装成一个对象&#xff0c;从而实现调用对象和执行对象之间的解耦&#xff0c;方便扩展和修改。 本文将和大家分享 JavaScript 中的…