Elixir中raise与throw的区别及异常无法捕获问题咨询
Elixir中
raise和throw的区别及问题解析 核心区别
throw:从Erlang继承的特性,本质是流程控制工具,而非错误处理机制。它可以抛出任意类型的数据(原子、字符串、结构体等),多用于复杂流程(比如递归遍历)中提前跳出并返回值,需要用catch捕获。不会自动生成栈追踪,性能开销极低。raise:Elixir专门用于错误/异常场景的机制,用来标识程序遇到了预期外的故障。要求抛出的是合法异常模块(如RuntimeError)、异常结构体,或直接传字符串(会自动包装为RuntimeError)。抛出后会生成完整栈追踪,需要用rescue捕获。
你的代码报错原因分析
你代码中Circuits.UART.open返回的错误原因是原子:enoent(对应“文件/设备不存在”):
- 用
throw(reason)正常,因为throw接受任意数据,只是把:enoent抛出去等待上层catch处理。 - 用
raise(reason)出错,是因为Elixir会把传入的原子:enoent当成异常模块,尝试调用:enoent.exception([])生成异常实例,但:enoent并非实现了exception/1函数的模块,因此直接抛出UndefinedFunctionError,且无法被预期逻辑捕获。
修正方案
如果想用raise处理该错误,需将原子原因转换为合法异常形式,比如:
# 方式1:直接抛出带错误信息的字符串(自动包装为RuntimeError) raise "串口无法打开,错误原因: #{inspect(reason)}" # 方式2:显式使用RuntimeError结构体 raise RuntimeError, message: "串口无法打开,错误原因: #{inspect(reason)}"
内容的提问来源于stack exchange,提问作者Chen Yu
相关产品推荐
相关产品推荐

