Elixir学习笔记——try, catch, and rescue

Elixir 有三种错误机制:errors, throws, and exits。在本章中,我们将探索每种机制,并说明何时应使用它们。

Errors

当代码中发生异常时,就会使用错误(或异常)。可以通过尝试将数字添加到原子来检索示例错误:

可以使用 raise/1 随时引发运行时错误:

可以使用 raise/2 传递错误名称和关键字参数列表来引发其他错误:

您还可以通过创建模块并在其中使用 defexception/1 构造来定义自己的错误。这样,您将创建一个与定义它的模块同名的错误。最常见的情况是使用消息字段定义自定义异常:

可以使用 try/rescue 构造来rescue错误:

上面的示例挽救了运行时错误并返回了异常本身,然后在 iex 会话中打印出来。

如果您对异常没有任何用处,则不必传递变量来rescue:

实际上,Elixir 开发人员很少使用 try/rescue 构造。例如,许多语言会强制您在无法成功打开文件时挽救错误。 Elixir 提供了一个 File.read/1 函数,该函数返回一个元组,其中包含有关文件是否已成功打开的信息:

这里没有 try/rescue。如果您想要处理打开文件的多个结果,可以使用 case 构造进行模式匹配:

对于您确实希望文件存在的情况(并且缺少该文件确实是一个错误),您可以使用 File.read!/1:

归根结底,由您的应用程序来决定打开文件时的错误是否是异常。这就是为什么 Elixir 不对 File.read/1 和许多其他函数施加异常的原因。相反,它让开发人员选择最佳的处理方式。

标准库中的许多函数都遵循这样的模式:有一个对应的函数会引发异常,而不是返回要匹配的元组。惯例是创建一个函数 (foo),它返回 {:ok, result} 或 {:error,reason} 元组,以及另一个函数 (foo!,同名但末尾带有 !),它采用与 foo 相同的参数,但如果出现错误则会引发异常。如果一切顺利,foo! 应该返回结果(未包装在元组中)。File 模块就是此惯例的一个很好的例子。

快速失败/让它崩溃

在 Erlang 社区和 Elixir 社区中,有一句俗语很常见,那就是“快速失败”/“让它崩溃”。让它崩溃背后的想法是,如果发生意外,最好让异常发生,而不是去挽救它。

强调“意外”这个词很重要。例如,假设您正在构建一个处理文件的脚本。您的脚本接收文件名作为输入。预计用户可能会犯错误并提供未知的文件名。在这种情况下,虽然您可以使用 File.read!/1 读取文件并在文件名无效的情况下让它崩溃,但使用 File.read/1 并向脚本用户提供清楚而准确的错误反馈可能更有意义。

其他时候,您可能完全期望某个文件存在,如果不存在,则意味着其他地方发生了严重错误。在这种情况下,File.read!/1 就是您所需要的。

第二种方法也有效,因为如“进程”一章中所述,所有 Elixir 代码都在隔离的进程内运行,默认情况下不共享任何内容。因此,进程中未处理的异常永远不会崩溃或破坏另一个进程的状态。这使我们能够定义主管进程,用于观察进程何时意外终止,并在其位置启动一个新进程。

归根结底,“快速失败”/“让它崩溃”是一种说法,当发生意外情况时,最好从主管新启动的新进程中重新开始,而不是盲目地尝试挽救所有可能的错误情况,而没有完整的错误发生时间和方式背景。

重新引发

虽然我们通常避免在 Elixir 中使用 try/rescue,但我们可能希望使用此类构造的一种情况是可观察性/监控。假设您想要记录出现错误的情况,您可以这样做:

在上面的例子中,我们挽救了异常,记录了它,然后重新引发了它。我们在格式化异常和重新引发时都使用 __STACKTRACE__ 构造。这确保我们按原样重新引发异常,而不会更改值或其来源。

一般来说,我们在 Elixir 中按字面意思理解错误:它们保留用于意外和/或异常情况,从不用于控制代码流程。如果您确实需要流控制构造,则应使用 throws。这就是我们接下来要看到的内容。

Throws

在 Elixir 中,可以抛出一个值,然后将其捕获。throw 和 catch 保留用于除非使用 throw 和 catch 否则无法检索值的情况。

这些情况在实践中并不常见,除非与未提供适当 API 的库交互。例如,假设 Enum 模块没有提供任何用于查找值的 API,而我们需要在数字列表中找到 13 的第一个倍数:

由于 Enum 确实提供了适当的 API,因此在实践中 Enum.find/2 是可行的方法:

Exits

所有 Elixir 代码都在相互通信的进程内运行。当进程因“自然原因”(例如未处理的异常)死亡时,它会发送退出信号。进程也可以通过明确发送退出信号而死亡:

在上面的例子中,链接进程通过发送值为 1 的退出信号而死亡。Elixir shell 会自动处理这些消息并将其打印到终端。

也可以使用 try/catch“捕获”退出:

catch 也可以在函数体内使用,而无需匹配 try。

但是,使用 try/catch 已经不常见了,使用它来捕获退出就更少了。

退出信号是 Erlang VM 提供的容错系统的重要组成部分。进程通常在监督树下运行,而监督树本身就是监听受监督进程的退出信号的进程。一旦收到退出信号,监督策略就会启动,受监督进程就会重新启动。

正是这种监督系统使得 try/catch 和 try/rescue 等结构在 Elixir 中如此罕见。我们宁愿“快速失败”,而不是挽救错误,因为监督树将保证我们的应用程序在发生错误后回到已知的初始状态。

After

有时,需要确保在执行某些可能引发错误的操作后清理资源。try/after 构造允许您这样做。例如,我们可以打开一个文件并使用 after 子句将其关闭 - 即使出现问题:

无论 tried 块是否成功,after 子句都会执行。但请注意,如果链接的进程退出,则该进程将退出,并且 after 子句将不会运行。因此 after 仅提供软保证。幸运的是,Elixir 中的文件也链接到当前进程,因此如果当前进程崩溃,它们将始终被关闭,与 after 子句无关。您会发现其他资源(如 ETS 表、套接字、端口等)也是如此。

有时您可能希望将函数的整个主体包装在 try 构造中,通常是为了保证之后会执行一些代码。在这种情况下,Elixir 允许您省略 try 行:

每当指定 after、rescue 或 catch 之一时,Elixir 都会自动将函数主体包装在 try 中。

Else

如果存在 else 块,则每当 try 块完成且没有抛出或错误时,它都会与 try 块的结果匹配。

else 块中的异常不会被捕获。如果 else 块内没有匹配的模式,则会引发异常;当前 try/catch/rescue/after 块不会捕获此异常。

变量作用域

与 Elixir 中的 case、cond、if 和其他构造类似,在 try/catch/rescue/after 块内定义的变量不会泄漏到外部上下文。换句话说,此代码无效:

相反,您应该返回 try 表达式的值:

此外,在 try 的 do 块中定义的变量在 rescue/after/else 内也不可用。这是因为 try 块可能随时失败,因此变量可能从未被绑定过。所以这也不有效:

至此我们对 try、catch 和 rescue 的介绍就结束了。您会发现它们在 Elixir 中的使用频率低于在其他语言中。接下来我们将讨论对 Elixir 开发人员来说非常重要的一个主题:编写文档。

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

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

相关文章

生活好物:日常更精彩

我们的日用杂货店,是生活美学的聚集地。这里汇聚了各式各样的生活用品,每一件都蕴含着对生活的热爱与追求。 走进我们的日用杂货店,仿佛打开了一个充满生活气息的宝藏盒。从厨房的锅碗瓢盆,到浴室的洗漱用品,再到客厅的…

6.17 作业

使用qt实现优化自己的登录界面 要求: 1. qss实现 2. 需要有图层的叠加 (QFrame) 3. 设置纯净窗口后,有关闭等窗口功能。 4. 如果账号密码正确,则实现登录界面关闭,另一个应用界面显示。 第一个源文件 …

9.无代码爬虫软件做网页数据抓取流程——弹出窗口的移除

首先,多数情况下免费版本的功能,已经可以满足绝大多数采集需求,想了解八爪鱼采集器版本区别的详情,请访问这篇帖子: https://blog.csdn.net/cctv1123/article/details/139581468 八爪鱼采集器免费版和个人版、团队版下…

架构师工作报告

一、需求分析与技术选型 工作内容概述: 深入理解项目需求,参与需求评审,确保需求的完整性和可行性。 根据需求制定技术方案,选择合适的技术栈、架构模式和工具。 工作量要求: 参与需求评审会议,通常每周1-2…

流式接口解析及数据展示

前言 此处为一个流式接口的对话&#xff0c;前端需要以流式的方式进行输出。前端框架使用Vue3 HTML 说明&#xff1a;此处将展示对话内容的多于元素已删除&#xff0c;只保留了消息体的HTML。 <div v-for"item in data" class"chat-item"><di…

反射复习(java)

文章目录 反射机制的作用反射机制的原理加载机制详细解释 获取 Class 对象反射获取构造方法&#xff1a;获取 Class 对象里面 Constructor 对象反射获取成员变量&#xff1a;获取Class 对象里面的 Field 对象反射获取成员方法&#xff1a;获取 Class 对象里的 Method 对象其他常…

15.编写自动化测试(下)

标题 三、控制测试流程3.1 添加测试参数3.2 并行或连续运行测试3.3 显示函数输出3.4 指定/过滤测试用例名称3.5 忽略某些测试用例3.6 只运行被忽略的测试 四、测试的组织结构4.1 概念引入4.2 测试私有函数4.2 单元测试4.3 集成测试4.4 集成测试中的子模块4.5 二进制crate的集成…

Python脚本中使用 if 语句导致的错误代码

在 Python 脚本中使用 if 语句是一种常见的控制流程结构&#xff0c;用于根据条件决定程序的执行路径。当使用 Python 中的 if 语句时&#xff0c;可能会导致一些常见的错误。下面就是我经常遇到的错误代码示例及其可能的原因和解决方法&#xff0c;希望对大家有些帮助&#xf…

深入解析Spring Cloud:微服务架构的利器(下)

在上一篇文章中&#xff0c;我们介绍了Spring Cloud的基本概念、核心组件以及如何在Java项目中使用Spring Cloud进行服务注册与发现。本文将继续探讨Spring Cloud的负载均衡、配置管理、服务熔断和API网关等高级特性。 4. 负载均衡 4.1 使用Ribbon Spring Cloud Ribbon是一个…

死锁预防之银行家算法

死锁预防之银行家算法 第一章 概述 Dijkstra提出了一种能够避免死锁的调度算法,称为银行家算法。 它的模型基于一个小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,每个客户都有一个贷款额度,银行家知道不可能所有客户同时都需要最大贷款额,所以他只保留一定单位…

韩国职场新趋势:员工拒绝晋升,追求工作与生活的平衡

在当前职场环境中&#xff0c;晋升通常被视为职业生涯发展的重要里程碑。然而&#xff0c;据韩国《今日财经》报道&#xff0c;现代重工工会在今年的劳资谈判中提出了一个令人关注的要求——“拒绝晋升权”。这一要求反映了韩国职场的新趋势&#xff0c;即越来越多的员工对高薪…

长期保存红酒的挑战与应对策略

云仓酒庄雷盛红酒&#xff0c;以其卓着的品质和口感&#xff0c;赢得了无数葡萄酒爱好者的喜爱。然而&#xff0c;对于那些希望长期保存这些珍贵佳酿的人来说&#xff0c;如何确保红酒的品质和风味不受时间的影响&#xff0c;却是一项充满挑战的任务。 长期保存红酒的大挑战来自…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 火星字符串(100分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

电影《加菲猫家族》观后感

上周看了电影《加菲猫家族》&#xff0c;本片其中有很多明亮的画面&#xff0c;相关艳丽的色彩&#xff0c;充满温馨的场景&#xff0c;很符合加菲猫的一贯画风&#xff0c;即使反派出场时&#xff0c;带有阴暗的感觉&#xff0c;看起也不是特别吓人&#xff0c;比较欢乐气氛&a…

定时器介绍之8253芯片

目录 定时器简介 8253功能介绍 组成 工作原理 相关引脚 启动方法 计数方式 实现 读取计数值 定时器简介 8253功能介绍 内部结构 相关引脚 计数器组成 工作原理 启动方法 计数方式 初始化&#xff1a;写入控制字——>写入计数初值 实现 计数长度选择&#xff1a…

jingxiang制作

文章目录 jingxiang制作为什么需要jingxiang制作如何进行jingxiang制作 快照方式制作jingxiang制作命令do cker commit 快照制作jingxiang创建临时工作目录编写一个实例代码启动一个容器替换国内软件源安装编译软件源代码拷贝到容器中编译运行提交为一个jingxiang测试是否可以正…

金额工具类:数字转字符串(每三位以逗号分隔)

问题背景 要求实现一个金额转换的工具类,输入一个数字金额,返回新的字符串,每三位以逗号分隔。 例如: 输入:1000 输出:1,000输入:5689104 输出:5,689,104输入:12345678 输出:12,345,678代码实现 /*** @description 数组格式化, 每三位以逗号分隔* @date 2024-6-1…

虚拟机Ping不通主机

1.问题描述 虚拟机IP&#xff1a; 192.168.3.133 主机ip&#xff1a;192.168.3.137 虚拟机Ping不通主机 主机可以ping通虚拟机 2.解决方案 设置桥接模式 控制面板找到网络和Internet设置 3.问题解决

数据库基础——数字、字符串、日期时间、二进制

数据库的分类 定义&#xff1a;主要是数据表的创建、删除、修改 操纵&#xff1a;对数据进行增删添改 控制&#xff1a;对数据库的权限进行管理 数据库不区分大小写&#xff0c;一条语句的结尾以英文分号结尾 命名不能是关键字&#xff0c;只能使用英文、数字和下划线 注释可以…

实施细则!2024年四川省科学技术奖励办法申报条件、要求、对象及材料整理

2024年四川省科学技术奖励办法申报条件、要求、对象及材料整理如下&#xff0c;四川省的企业单位可以了解一下 第一章  总 则 第一条 为做好四川省科学技术奖励工作&#xff0c;规范评审程序&#xff0c;保障四川省科学技术奖(以下简称“省科学技术奖”)的评审质量&#xf…