我有一个get_url_content
函数而不关心错误(这只是一个测试)。它返回Option<String>
。
extern crate hyper;
use std::io::Read;
use hyper::client::Client;
fn get_url_content(url: &str) -> Option<String> {
let client = Client::new();
let mut s = String::new();
match client.get(url).send() {
Ok(mut res) => {
match res.read_to_string(&mut s) {
Ok(_) => {
Some(s)
},
Err(_) => {
None
}
}
},
Err(_) => {
None
}
}
}
此功能正常但我发现它不容易阅读。我认为有一些关于此类案例的最佳实践,以使其更具可读性。嵌套匹配是不好的做法(如JS中的回调地狱),如果是,如何避免它?
答案 0 :(得分:9)
让事情变得更清洁的最简单方法是放下一些括号:
match client.get(url).send() {
Ok(mut res) =>
match res.read_to_string(&mut s) {
Ok(_) => Some(s),
Err(_) => None,
},
Err(_) => None,
}
内部匹配可以表达得更清晰一点
match client.get(url).send() {
Ok(mut res) =>
res.read_to_string(&mut s).ok().map(|_| s),
Err(_) => None,
}
这表示在外部类型上使用map
(获取Result<Option<_>, _>
),然后使用.unwrap_or(None)
或.unwrap_or_default()
client.get(url).send()
.map(|mut res| res.read_to_string(&mut s).ok().map(|_| s))
.unwrap_or(None)
答案 1 :(得分:4)
Result
和Option
有一些很好的方法可以让代码变得更简单。
fn get_url_content(url: &str) -> Option<String> {
let client = Client::new();
let res = client.get(url)
.send()
.ok() // Convert to Option, discarding error
.and_then(|mut res| {
let mut s = String::new();
let result = res.read_to_string(&mut s);
result.ok().map(|_| s)
}
})
}
我建议查看Result和Option的文档;它们之间存在大多数转换组合的方法,并且对成功或错误的一半采取行动。
如果您可以更改get_url_content
以返回Result
,我建议您(请参阅the error handling documentation。使用您自己的错误类型和From
的某些实现,该功能然后变成(
fn get_url_content(url: &str) -> Result<String, MyError> {
let client = Client::new();
let mut s = String::new();
let got = try!(client.get(url));
let sent = try!(got.send());
try!(sent.read_to_string(s));
Ok(s)
}
使用新的?
运算符可能更简单。