面试题答案
一键面试try
方法在处理嵌套Result
类型时的行为和原理- 行为:
try
方法(在Rust 2018及以后版本中使用?
语法糖替代)用于从Result
类型中提取值,如果Result
是Ok
,则提取其中的值并继续执行后续代码;如果Result
是Err
,则直接返回这个Err
值,将错误传播出去。 - 原理:
?
语法糖会调用FromResidual
trait的from_residual
方法,将Result
中的Err
值转换为函数的返回类型中的Err
值。对于嵌套的Result
类型,它会一层一层地处理,只要遇到Err
就停止处理并返回错误。
- 行为:
- 通过
try
方法串联函数链func1 -> func2 -> func3
假设func1
、func2
、func3
函数定义如下:
fn func1() -> Result<i32, String> {
// 模拟一些操作,返回Ok或Err
Ok(1)
}
fn func2(input: i32) -> Result<i32, String> {
// 模拟一些操作,返回Ok或Err
Ok(input * 2)
}
fn func3(input: i32) -> Result<i32, String> {
// 模拟一些操作,返回Ok或Err
Ok(input + 3)
}
使用try
方法(?
语法糖)串联这些函数:
fn chain_functions() -> Result<i32, String> {
let result1 = func1()?;
let result2 = func2(result1)?;
let result3 = func3(result2)?;
Ok(result3)
}
在这个例子中,如果func1
返回Err
,则chain_functions
函数直接返回这个Err
,不会执行func2
和func3
;如果func1
返回Ok
,则提取值传递给func2
,以此类推。
3. 使用unwrap
而不是try
的后果
unwrap
行为:unwrap
方法用于从Result
类型中提取值,如果Result
是Ok
,则返回其中的值;如果Result
是Err
,则会导致程序panic。- 不同后果:在函数链
func1 -> func2 -> func3
中,如果在某个函数中使用unwrap
而不是try
,例如在func2
中使用unwrap
:
fn chain_functions_with_unwrap() -> i32 {
let result1 = func1().unwrap();
let result2 = func2(result1).unwrap();
let result3 = func3(result2).unwrap();
result3
}
如果func1
、func2
或func3
返回Err
,程序就会panic。这意味着错误不会像使用try
那样被正确传播,而是直接导致程序异常终止,这在生产环境中是非常危险的,可能会导致数据丢失或未处理的错误情况。相比之下,使用try
方法可以让错误以一种更可控的方式在函数调用链中传播,调用者可以选择如何处理这些错误,而不是直接让程序崩溃。