不同失败需要不同处理时,应该用throws或Result保留原因,而不是用try?抹去。throws沿调用流程传递错误;Result把成功或失败保存为值,供稍后处理。
原理与设计判断
ParseError区分非数字输入和负数。throws(ParseError)明确指定错误类型,do-catch即可据此选择响应。try?把两种失败都变成nil,当恢复策略不同时,这样的信息不够。 一手资料
复现代码
将cat、-1、0、42交给同一个解析器。先确认try?使两种失败都得到nil,再把结果保存为Result<Int, ParseError>。typed do代码块明确指定catch的错误类型,get则取回成功值或重新抛出失败。
这个独立示例已于 2026-10-23 使用 Apple Swift 6.4,以 Swift 6 语言模式在 arm64 macOS 目标环境运行。不需要网络或额外软件包。
请在下载文件的文件夹中运行。检查不通过时,precondition 会终止程序。请勿使用 -Ounchecked,因为它会移除这些检查。
swift -swift-version 6 swift-error-handling-throws-result.swift
enum ParseError: Error, Equatable { case notInteger, negative }
func parse(_ raw: String) throws(ParseError) -> Int {
guard let value = Int(raw) else { throw .notInteger }
guard value >= 0 else { throw .negative }
return value
}
precondition((try? parse("cat")) == nil && (try? parse("-1")) == nil)
let results: [Result<Int, ParseError>] = ["cat", "-1", "0", "42"].map { raw in
do throws(ParseError) { return .success(try parse(raw)) }
catch { return .failure(error) }
}
precondition(results == [.failure(.notInteger), .failure(.negative), .success(0), .success(42)])
do {
_ = try results[1].get()
preconditionFailure("failure was lost")
} catch ParseError.negative {}
let recovered = try results[3].get()
precondition(recovered == 42)
print("try?-failures=nil,nil result=notInteger,negative,0,42 get-error=negative")
运行结果与解读
try?-failures=nil,nil result=notInteger,negative,0,42 get-error=negative
结果数组分别保留notInteger、negative、0、42。对失败结果调用get会再次抛出negative,成功结果则得到42。这项错误信息保留验证不需要网络或文件I/O。
适用范围与限制
throws不能捕获所有程序失败。强制解包或precondition违反造成的陷阱不在此契约内,try!失败也不应作为正常恢复路径。本实验只运行同步解析,未验证异步取消、重试或文件错误。
接下来要确认的事
根据调用方需要采取的不同行动定义错误。简单缺失值可用Optional;传递原因用throws;存储或汇总结果用Result。UI提示与日志适合在保留真实原因的边界接入。
来源与验证
- The Swift Programming Language: Error HandlingSwift.org · 官方文档 · 核查 2026年10月23日依据: 实现契约与说明的依据。运行输出另由本文所附实验确认。

