前言

简单记录一下KotlinrunCatchingcatching的使用和注意事项,记录于此,方便自己查阅。

正文

runCatchingcatching 都是用于优雅处理异常的函数,但它们的应用场景和底层机制有本质区别。

简单来说,runCatching 是 Kotlin 标准库提供的通用异常捕获工具,而 catchingkotlinx.coroutines 库专为协程设计的、能安全处理协程取消机制的增强版本。

runCatching

runCatching通用异常捕获,是 Kotlin 提供的函数式异常处理方式。它会执行传入的 lambda 表达式,并将结果封装为 Result 对象。

  • 成功时:返回 Result.success(value)

  • 失败时:返回 Result.failure(exception)

优点:代码线性、可读性强,支持 maprecoveronSuccessonFailure 等链式操作,非常适合构建数据处理管道。

致命缺陷:它会捕获所有异常,包括协程用于实现取消机制的 CancellationException。如果在协程中使用,会导致协程无法被正确取消,引发“僵尸协程”等严重问题。

// ✅ 在普通同步代码中安全使用
val number = runCatching { "123".toInt() }
    .onFailure { it.printStackTrace() } // 务必记录日志
    .getOrNull() ?: 0

catching

catching:协程安全版,是 kotlinx.coroutines 库提供的扩展函数,可以看作是 runCatching 的协程安全替代品。它的核心逻辑是在捕获异常后,判断是否为 CancellationException,如果是则立即重新抛出,从而保证协程的取消信号能够正常向上传播。

使用前提:必须在项目中引入 kotlinx-coroutines-core 依赖。

import kotlinx.coroutines.catching // 注意 import 路径

// ✅ 在协程/挂起函数中安全使用
suspend fun fetchData(): Result<String> {
    return catching {
        // 网络请求等挂起操作
        api.getData()
    }.onFailure { e ->
        // 这里只会处理真正的业务异常
        // CancellationException 会被自动重新抛出,不会进入此块
        e.printStackTrace()
    }
}

对比

特性runCatchingcatching
所属库Kotlin 标准库 (kotlin)协程库 (kotlinx.coroutines)
适用场景普通同步代码、非挂起函数协程内部、挂起函数 (suspend)
异常处理捕获所有 Throwable捕获所有 Throwable,但会重新抛出CancellationException
协程安全性不安全,会破坏协程取消机制安全,保证结构化并发
返回类型Result<T>Result<T>

小结

如果你在协程中必须使用 runCatching(例如,无法引入协程库或调用第三方非协程 API),请务必手动处理 CancellationException,否则将破坏协程的结构化并发。

补救措施:在 onFailure 中手动检查并重新抛出取消异常。

// ⚠️ 协程中使用 runCatching 的补救写法
runCatching {
    suspendFunction()
}.onFailure { e ->
    // 🔴 极其重要:必须将取消异常重新抛出!
    if (e is CancellationException) throw e

    // 处理其他业务异常
    e.printStackTrace()
}
  1. 普通同步代码:放心使用 runCatching,享受其函数式编程的便利。

  2. 协程/挂起函数优先使用 catching。这是最安全、最推荐的做法。

  3. 协程中被迫使用 runCatching:必须在 onFailure 中手动 throw CancellationException,作为安全兜底。

  4. 通用原则:无论使用哪个函数,在 onFailure务必记录异常日志,避免异常被静默吞掉,导致线上问题难以排查。

参考文章

  1. AI

  2. biumall

相关文章

笔友城堡 - 可定义的个人主页

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

none
暂无评论...