首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐
2025年5月22日 星期四 10:32pm

Kotlin Result 类型扩展详解 —— 新手使用指南

  • 25-04-17 10:20
  • 4363
  • 11393
juejin.cn

Result 是 Kotlin 标准库中用于封装成功或失败结果的类型,特别适合函数式错误处理。本文将详细扩展 Result 的各种使用场景,包括依赖关系、选择关系和对协程的支持。

一、基本 Result 使用

首先回顾基本用法:

kotlin
代码解读
复制代码
fun divide(a: Int, b: Int): Result<Int> { return if (b == 0) { Result.failure(ArithmeticException("Division by zero")) } else { Result.success(a / b) } } fun main() { val result = divide(10, 2) result.onSuccess { println("Result: $it") } .onFailure { println("Error: ${it.message}") } }

二、依赖关系处理

2.1 一对一依赖(线性依赖)

kotlin
代码解读
复制代码
// 一个操作依赖于前一个操作的结果 fun processUserData(userId: String): Result { return fetchUser(userId) .flatMap { user -> validateUser(user) } .map { validUser -> formatUserData(validUser) } } private fun fetchUser(id: String): Result { return if (id.isNotEmpty()) Result.success(User(id, "John")) else Result.failure(IllegalArgumentException("Invalid ID")) } private fun validateUser(user: User): Result { return if (user.name.isNotEmpty()) Result.success(user) else Result.failure(IllegalArgumentException("Invalid user")) } private fun formatUserData(user: User): String { return "User: ${user.name} (ID: ${user.id})" } data class User(val id: String, val name: String) fun main() { processUserData("123").fold( onSuccess = { println(it) }, onFailure = { println("Error: ${it.message}") } ) }

2.2 一对多依赖(一个操作依赖多个独立操作)

kotlin
代码解读
复制代码
// 多个独立操作,全部成功才能继续 fun processOrder(orderId: String, userId: String): Result { return Result.runCatching { val user = fetchUser(userId).getOrThrow() val order = fetchOrder(orderId).getOrThrow() val inventory = checkInventory(order.items).getOrThrow() OrderResult(user, order, inventory) } } // 模拟其他函数 private fun fetchOrder(id: String): Result = Result.success(Order(id, listOf("item1", "item2"))) private fun checkInventory(items: List<String>): Result<Boolean> = Result.success(true) data class Order(val id: String, val items: List) data class OrderResult(val user: User, val order: Order, val hasInventory: Boolean) fun main() { processOrder("order123", "user123").fold( onSuccess = { println("Order processed: $it") }, onFailure = { println("Failed to process order: ${it.message}") } ) }

2.3 多对一依赖(多个操作可以独立失败)

kotlin
代码解读
复制代码
// 多个操作,收集所有结果(成功或失败) fun collectMultipleResults(): Result>> { val results = listOf( fetchUser("1"), fetchProduct("p1"), fetchSettings("s1") ) return Result.success(results) } // 或者只关心成功的部分 fun collectSuccessfulResults(): List { return listOf( fetchUser("1"), fetchProduct("p1"), fetchSettings("s1") ).filter { it.isSuccess }.map { it.getOrNull()!! } } // 模拟函数 private fun fetchProduct(id: String): Result = Result.success(Product(id)) private fun fetchSettings(id: String): Result = Result.failure(IllegalStateException("Settings unavailable")) data class Product(val id: String) data class Settings(val config: String) fun main() { println("All results:") collectMultipleResults().getOrThrow().forEach { println(it) } println("\nSuccessful results:") println(collectSuccessfulResults()) }

三、选择关系(替代方案)

kotlin
代码解读
复制代码
// 尝试多个操作,使用第一个成功的 fun findAlternativeResource(): Result { return fetchPrimaryResource() .recoverCatching { fetchSecondaryResource().getOrThrow() } .recoverCatching { fetchFallbackResource().getOrThrow() } } // 或者更简洁的写法 fun findAlternativeResource2(): Result { return listOf( { fetchPrimaryResource() }, { fetchSecondaryResource() }, { fetchFallbackResource() } ).firstSuccess() } // 扩展函数:获取第一个成功的Result fun List<() -> Result>.firstSuccess(): Result { for (operation in this) { operation().onSuccess { return Result.success(it) } } return Result.failure(IllegalStateException("All operations failed")) } // 模拟函数 private fun fetchPrimaryResource(): Result = Result.failure(IOException("Primary unavailable")) private fun fetchSecondaryResource(): Result = Result.failure(IOException("Secondary unavailable")) private fun fetchFallbackResource(): Result = Result.success("Fallback data") fun main() { findAlternativeResource().fold( onSuccess = { println("Resource: $it") }, onFailure = { println("All attempts failed: ${it.message}") } ) findAlternativeResource2().fold( onSuccess = { println("Alternative resource: $it") }, onFailure = { println("All alternatives failed: ${it.message}") } ) }

四、Result 集合处理

kotlin
代码解读
复制代码
// 处理Result集合的几种方式 // 1. 全部成功才成功 fun processAllOrFail(results: List<Result<Int>>): ResultInt>> { return results.fold(Result.success(emptyList())) { acc, result -> acc.flatMap { list -> result.map { list + it } } } } // 2. 收集所有结果(成功和失败分开) data class PartitionedResults<T>(val successes: List, val failures: List) fun partitionResults(results: List<Result<T>>): PartitionedResults { return results.fold(PartitionedResults(emptyList(), emptyList())) { acc, result -> result.fold( onSuccess = { acc.copy(successes = acc.successes + it) }, onFailure = { acc.copy(failures = acc.failures + it) } ) } } // 3. 只收集成功的 fun getAllSuccesses(results: List<Result<T>>): List { return results.mapNotNull { it.getOrNull() } } fun main() { val results = listOf( Result.success(1), Result.failure(RuntimeException("Error 1")), Result.success(2), Result.failure(IllegalStateException("Error 2")), Result.success(3) ) println("All or nothing:") println(processAllOrFail(results)) println("\nPartitioned:") println(partitionResults(results)) println("\nOnly successes:") println(getAllSuccesses(results)) }

五、协程支持

kotlin
代码解读
复制代码
import kotlinx.coroutines.* import java.io.IOException // 协程中的Result使用 suspend fun fetchUserData(userId: String): Result = withContext(Dispatchers.IO) { Result.runCatching { // 模拟网络请求 delay(1000) if (userId == "error") throw IOException("Network error") "Data for $userId" } } suspend fun fetchUserProfile(userId: String): Result = withContext(Dispatchers.IO) { Result.runCatching { delay(500) if (userId == "invalid") throw IllegalStateException("Invalid user") "Profile of $userId" } } // 并行获取多个数据 suspend fun fetchMultipleData(userId: String): Result> = coroutineScope { val deferredData = async { fetchUserData(userId) } val deferredProfile = async { fetchUserProfile(userId) } val dataResult = deferredData.await() val profileResult = deferredProfile.await() if (dataResult.isSuccess && profileResult.isSuccess) { Result.success(Pair(dataResult.getOrThrow(), profileResult.getOrThrow())) } else { val exceptions = listOfNotNull( dataResult.exceptionOrNull(), profileResult.exceptionOrNull() ) Result.failure(exceptions.firstOrNull() ?: Exception("Unknown error")) } } // 使用recoverWith处理异步错误 suspend fun fetchWithFallback(userId: String): Result { return fetchUserData(userId) .recoverCatching { fetchUserProfile(userId).getOrThrow() } } fun main() = runBlocking { println("Successful case:") fetchMultipleData("123").fold( onSuccess = { println(it) }, onFailure = { println("Error: ${it.message}") } ) println("\nError case:") fetchMultipleData("error").fold( onSuccess = { println(it) }, onFailure = { println("Error: ${it.message}") } ) println("\nRecovery case:") fetchWithFallback("error").fold( onSuccess = { println("Fetched: $it") }, onFailure = { println("Failed: ${it.message}") } ) }

六、实用扩展函数

kotlin
代码解读
复制代码
// 一些有用的Result扩展函数 // 将多个Result合并为一个 fun Result.combine(other: Result<T2>): Result> { return this.flatMap { t1 -> other.map { t2 -> t1 to t2 } } } // 将List>转换为Result> fun List>.sequence(): Result> { return this.fold(Result.success(emptyList())) { acc, result -> acc.flatMap { list -> result.map { list + it } } } } // 过滤成功的Result fun List>.filterSuccess(): List { return this.mapNotNull { it.getOrNull() } } // 执行副作用并返回原始Result fun Result.onSuccess(action: (T) -> Unit): Result { this.onSuccess { action(it) } return this } fun Result.onFailure(action: (Throwable) -> Unit): Result { this.onFailure { action(it) } return this } fun main() { val r1 = Result.success(1) val r2 = Result.success("two") val r3 = Result.failure<Boolean>(RuntimeException("Error")) println("Combine:") println(r1.combine(r2)) println(r1.combine(r3)) println("\nSequence:") val results = listOf(r1, r2.map { it.length }, Result.success(3.0)) println(results.sequence()) println("\nFilter success:") val mixedResults = listOf(r1, r2, r3) println(mixedResults.filterSuccess()) }

七、总结

  1. 依赖关系:

    • 一对一:使用 flatMap 或 map 链式调用
    • 一对多:使用 runCatching 组合多个操作
    • 多对一:收集多个独立操作的结果
  2. 选择关系:

    • 使用 recover 或 recoverCatching 提供备用方案
    • 实现 firstSuccess 选择第一个成功的操作
  3. 集合处理:

    • sequence 转换 List> 为 Result>
    • 分区处理成功和失败的结果
  4. 协程支持:

    • 在挂起函数中使用 Result.runCatching
    • 并行执行多个异步操作并组合结果
  5. 扩展函数:

    • 创建实用扩展函数使 Result 处理更简洁

这些模式可以帮助你在Kotlin中构建健壮的错误处理流程,特别是在复杂的异步或依赖操作场景中。

更多分享

  1. 一文吃透Kotlin中冷流(Clod Flow)和热流(Hot Flow)
  2. 一文带你吃透Kotlin协程的launch()和async()的区别
  3. Kotlin 委托与扩展函数——新手入门
  4. Kotlin 作用域函数(let、run、with、apply、also)的使用指南
  5. 一文带你吃透Kotlin中 lateinit 和 by lazy 的区别和用法
  6. Kotlin 扩展方法(Extension Functions)使用详解
  7. Kotlin 中 == 和 === 的区别
  8. Kotlin 操作符与集合/数组方法详解——新手指南
  9. Kotlin 中 reified 配合 inline 不再被类型擦除蒙蔽双眼
注:本文转载自juejin.cn的QING618的文章"https://juejin.cn/post/7491607061781676095"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top