Kotlin中使用inline高阶函数metrics时,如何避免非局部返回并保留简洁语义?
解决方案
针对你遇到的inline函数lambda中非局部return跳过metrics日志的问题,除了带标签的return,还有以下几种简洁的解决方式:
1. 移除lambda中的显式return,改用表达式体
这是最简洁的处理方式,Kotlin的单表达式lambda可以直接返回值,无需显式写return,这样就不会触发非局部返回,metrics的完整逻辑都会执行。
修改后的代码:
fun main() { println(job()) } fun job() : String = metrics { println("entering metrics function") "My String" // 直接返回字符串,无需return } inline fun metrics(block: () -> String): String { val result = block() println("Adding some metrics about result: $result") return result }
内联后的等价逻辑:
fun job() : String { println("entering metrics function") val result = "My String" println("Adding some metrics about result: $result") return result }
执行后会得到期望的输出:
entering metrics function Adding some metrics about result: My String My String
2. 用crossinline修饰lambda参数
crossinline关键字可以禁止inline函数的lambda使用非局部返回,从编译层面避免意外跳过metrics的后续逻辑。此时如果lambda里写return会直接报错,强制你要么去掉return,要么使用带标签的return(但标签return此时仅返回lambda,而非外层函数)。
修改后的metrics函数:
inline fun metrics(crossinline block: () -> String): String { val result = block() println("Adding some metrics about result: $result") return result }
此时job函数若保留return "My String"会编译失败,必须调整为不带return的表达式体,或者使用return@metrics "My String"(后者语义明确,且不会跳出外层函数)。
3. 移除inline修饰符(不推荐)
如果对性能要求不高,可以去掉metrics函数的inline关键字,此时lambda会被编译为匿名类实例,lambda中的return默认只能返回lambda本身(非局部return会被编译器禁止),metrics的日志逻辑会正常执行。不过这种方式会带来额外的对象创建开销,不适合高频调用的场景。
修改后的代码:
fun metrics(block: () -> String): String { val result = block() println("Adding some metrics about result: $result") return result }
内容的提问来源于stack exchange,提问作者Pablo
相关产品推荐
相关产品推荐

