当前位置: 首页 > news >正文

西安手机网站建设动力无限wordpress 重复标题

西安手机网站建设动力无限,wordpress 重复标题,网页百度网盘,网站推广软件价格开发环境 Windows 10Rust 1.67.1VS Code 1.75.1项目工程 这里继续沿用上次工程rust-demo 带结果信息的可恢复错误 大多数错误并没有严重到需要程序完全停止的程度。有时#xff0c;当一个函数失败时#xff0c;它的原因是你可以很容易地解释和应对的。例如#xff0c;如…开发环境 Windows 10Rust 1.67.1VS Code 1.75.1项目工程 这里继续沿用上次工程rust-demo 带结果信息的可恢复错误 大多数错误并没有严重到需要程序完全停止的程度。有时当一个函数失败时它的原因是你可以很容易地解释和应对的。例如如果你试图打开一个文件但由于该文件不存在而导致操作失败你可能想创建该文件而不是终止该进程。 回顾前面章节中的 用结果处理潜在的失败结果枚举被定义为有两个变体Ok和Err如下例所示。 enum ResultT, E {Ok(T),Err(E), } T和E是通用类型参数我们将在后面章节中详细讨论通用类型。你现在需要知道的是T代表在Ok变量中成功情况下将被返回的值的类型E代表在Err变量中失败情况下将被返回的错误类型。因为Result有这些通用的类型参数我们可以在许多不同的情况下使用Result类型和定义在它上面的函数我们想返回的成功值和错误值可能不同。 让我们调用一个返回结果值的函数因为这个函数可能会失败。在下例3中我们尝试打开一个文件。 例3文件名 src/main.rs use std::fs::File;fn main() {let greeting_file_result File::open(hello.txt); // hello.txt是否存在println!(greeting_file_result {:?}, greeting_file_result ) }编译运行 cargo run File::open 的返回类型是一个 ResultT, E。通用参数T已经被File::open的实现填入了成功值的类型即std::fs::File它是一个文件句柄。错误值中使用的E的类型是std::io::Error。这个返回类型意味着对 File::open 的调用可能会成功并返回一个我们可以读取或写入的文件句柄。该函数的调用也可能失败例如该文件可能不存在或者我们可能没有访问该文件的权限。File::open函数需要有一种方法来告诉我们它是成功还是失败同时给我们提供文件柄或错误信息。这些信息正是Result枚举所传达的。 在File::open成功的情况下变量greeting_file_result中的值将是一个Ok的实例包含一个文件柄。在失败的情况下greeting_file_result中的值将是一个Err的实例包含关于发生的错误类型的更多信息。 我们需要在上例2中的代码中添加一些内容以便根据File::open返回的值采取不同的行动。下例3显示了一种使用基本工具处理结果的方法即我们在之前章节讨论过的match表达式。 例4文件名 src/main.rs use std::fs::File;fn main() {let greeting_file_result File::open(hello.txt);let greeting_file match greeting_file_result { // match表达式Ok(file) file,Err(error) panic!(Problem opening the file: {:?}, error),}; }请注意和Option枚举一样Result枚举和它的变体已经被前奏带入了范围所以我们不需要在匹配类中的Ok和Err变体之前指定Result::。 当结果为Ok时该代码将从Ok变量中返回内部文件值然后我们将该文件句柄值赋给变量greeting_file。match后我们可以使用文件句柄来读或写。 match的另一方面处理从File::open获取一个Err值的情况。在这个例子中我们选择了panic宏观。如果在我们的当前目录中没有名为hello.txt的文件并且我们运行了这段代码我们将会看到下面的输出panic宏: 编译运行 cargo run 像往常一样这个输出告诉我们到底哪里出错了。 不同错误的匹配 上例中的代码会panic不管为什么File::open失败。但是我们希望针对不同的失败原因采取不同的操作:如果File::open因为文件不存在而失败我们希望创建该文件并将句柄返回给新文件。如果File::open由于任何其他原因失败—例如因为我们没有打开文件的权限—我们仍然希望代码panic就像上例中一样。为此我们添加了一个内部match表达式如下例5所示。  例5文件名 src/main.rs use std::fs::File; use std::io::ErrorKind;fn main() {let greeting_file_result File::open(hello.txt);let greeting_file match greeting_file_result {Ok(file) file,Err(error) match error.kind() { // match错误类型ErrorKind::NotFound match File::create(hello.txt) { // 创建hello,extOk(fc) fc,Err(e) panic!(Problem creating the file: {:?}, e),},other_error {panic!(Problem opening the file: {:?}, other_error);}},}; }编译运行 cargo run File::open在Err内部返回值的类型是io::Error这是标准库提供的一个结构体。这个结构有一个方法kind我们可以调用它来获取io::ErrorKind值。枚举io::ErrorKind由标准库提供它具有代表io操作可能导致的不同类型错误的变量。我们要使用的变量是ErrorKind::NotFound这表明我们试图打开的文件尚不存在。所以我们在greeting_file_result上进行匹配但是在error.kind()上也有一个内部匹配。 我们要在内部匹配中检查的条件是error.kind()返回的值是否是ErrorKind枚举的NotFound变量。如果是我们尝试用File::create创建文件。然而因为File::create也可能失败所以我们需要在内部match表达式中增加一个分支。当无法创建文件时会打印一条不同的错误消息。外部match的第二个分支保持不变因此除了丢失文件错误之外程序还会对任何错误产生恐慌。 使用match Result TE 的替代方法 match的多了去了match表达式非常有用但也非常原始。在后面章节中你将学习闭包它与ResultTE 上定义的许多方法一起使用。在代码中处理ResultTE 值时这些方法比使用match更简洁。 例如这里有另一种方法来编写如上例中所示的逻辑这次使用闭包和unwrap_or_else方法: use std::fs::File; use std::io::ErrorKind;fn main() {let greeting_file File::open(hello.txt).unwrap_or_else(|error| {if error.kind() ErrorKind::NotFound {File::create(hello.txt).unwrap_or_else(|error| {panic!(Problem creating the file: {:?}, error);})} else {panic!(Problem opening the file: {:?}, error);}}); }尽管这段代码的行为与上例相同但它不包含任何match表达式读起来更清晰。在你读完后面章节后回到这个例子在标准库文档中查找unwrap_or_else方法。当您处理错误时更多的这些方法可以清理大量嵌套的match表达式。 出错时死机的快捷方式:unwrap和expect 使用match可以很好地工作但是它可能有点冗长并且不总是很好地传达意图。ResultTE 类型定义了许多方法来完成各种更具体的任务。unwrap方法是一个快捷方法就像我们在上例中编写的match表达式一样。如果Result值是Ok变量unwrap将返回Ok变量中的值。如果Result是Err变量unwrap将调用panic宏观对我们来说。下面是一个实际展开的例子: 文件名:src/main.rs use std::fs::File;fn main() {let greeting_file File::open(hello.txt).unwrap();println!(greeting_file {:?}, greeting_file); }运行 cargo run 如果我们在没有hello.txt文件的情况下运行这段代码我们将会看到一条来自panic的错误消息unwrap方法进行的调用: 同样expect方法也让我们选择panic错误消息。使用expect而不是unwrap并提供良好的错误消息可以传达您的意图并使跟踪死机的根源变得更容易。expect的语法如下例所示: 文件名:src/main.rs use std::fs::File;fn main() {let greeting_file File::open(hello.txt).expect(hello.txt should be included in this project);println!(greeting_file {:?}, greeting_file); }运行 cargo run 我们使用expect的方式和unwrap一样:返回文件句柄或者调用panic宏。expect在调用panic时使用的错误消息将是我们传递给expect的参数而不是默认的panicunwrap使用的消息。它看起来是这样的: 在生产质量的代码中大多数Rust程序员选择expect而不是unwrap并给出更多关于为什么操作预期总是成功的上下文。这样如果您的假设被证明是错误的您就有更多的信息用于调试。 传播误差 当函数的实现调用可能失败的东西时您可以将错误返回给调用代码以便它可以决定做什么而不是在函数本身中处理错误。这就是所谓的传播错误并给予调用代码更多的控制其中可能有比代码上下文中可用的更多的信息或逻辑来指示应该如何处理错误。 下例7显示了一个从文件中读取用户名的函数。如果该文件不存在或无法读取该函数将把这些错误返回给调用该函数的代码。 例6文件名:src/main.rs use std::fs::File; use std::io::{self, Read};fn read_username_from_file() - ResultString, io::Error {let username_file_result File::open(hello.txt);let mut username_file match username_file_result {Ok(file) file,Err(e) return Err(e),};let mut username String::new();match username_file.read_to_string(mut username) {Ok(_) Ok(username),Err(e) Err(e),} } 这个函数可以用更短的方式编写但是为了探索错误处理我们将从手工做大量的工作开始最后我们将展示更短的方法。我们先来看看函数的返回类型:ResultStringio::Error 。这意味着该函数正在返回类型Result TE 的值其中泛型参数T已经用具体类型String填充泛型类型E已经用具体类型io::Error填充。 如果这个函数成功没有任何问题调用这个函数的代码将收到一个Ok值该值包含一个String—这个函数从文件中读取的用户名。如果这个函数遇到任何问题调用代码将收到一个Err值该值包含io::Error的一个实例该实例包含有关问题的更多信息。我们选择io::Error作为这个函数的返回类型因为这恰好是我们在这个函数体中调用的可能失败的两个操作返回的错误值的类型:File::open函数和read_to_string方法。 函数体通过调用File::open函数开始。然后我们用类似于之前例子中的匹配来处理Result值。如果File::open成功模式变量file中的文件句柄将变成可变变量username_file中的值函数将继续运行。在Err的情况下而不是叫painc我们使用return关键字从函数中提前返回并将File::open中的错误值(现在在模式变量e中)作为该函数的错误值传递回调用代码。 因此如果我们在username_file中有一个文件句柄该函数就会在变量username中创建新String并在username_file中的文件句柄上调用read_to_string方法将文件内容读入username。read_to_string方法也返回一个Result因为它可能会失败即使File::open成功了。所以我们需要另一个匹配来处理这个结果:如果read_to_string成功了那么我们的函数就成功了我们从文件中返回username这个文件现在包含在一个Ok中。如果read_to_string失败我们返回错误值的方式与我们在处理File::open返回值的match中返回错误值的方式相同。但是我们不需要显式地说return因为这是函数中的最后一个表达式。 调用此代码的代码将处理获取包含用户名的Ok值或包含io::Error的Err值。由调用代码决定如何处理这些值。如果调用代码得到一个Err值它可能会调用panic并使程序崩溃使用默认用户名或者从文件以外的地方查找用户名。我们没有足够的信息来了解调用代码实际试图做什么所以我们向上传播所有的成功或错误信息以便它进行适当的处理。 这种传播错误的模式在Rust中非常普遍以至于Rust提供了问号运算符为了让事情变得简单 传播错误的快捷方式 ? 操作符 下例7显示了read_username_from_file的一个实现它具有与上例相同的功能但是这个实现使用了操作符。  例7文件名:src/main.rs use std::fs::File; use std::io::{self, Read};fn read_username_from_file() - ResultString, io::Error {let mut username_file File::open(hello.txt)?; // ? 操作符let mut username String::new();username_file.read_to_string(mut username)?; // ? 操作符Ok(username) }放置在Result值定义之后其工作方式与我们在上例中定义的处理结果值的match表达式几乎相同。如果Result的值是OkOk中的值将从这个表达式返回程序将继续。如果值是一个ErrErr将从整个函数中返回就像我们使用return关键字一样因此错误值将传播到调用代码。 上例中的match表达式和? 操作符所做的事情是有区别的被调用了? 操作符的错误值会经过标准库中的From特性中定义的from函数该函数用于将值从一种类型转换成另一种类型。当? 操作符调用from函数时收到的错误类型被转换为当前函数的返回类型中定义的错误类型。当一个函数返回一个错误类型时这很有用它代表了一个函数可能失败的所有方式即使部分函数可能因为许多不同的原因而失败。 例如我们可以改变上例7中的 read_username_from_file 函数来返回一个我们定义的名为 OurError 的自定义错误类型。如果我们也为OurError定义 impl Fromio::Error for io::Error构造一个OurError的实例那么read_username_from_file正文中的? 操作符调用将调用from并转换错误类型而不需要在函数中添加任何代码。 在上例的上下文中File::open调用的结尾处的? 将返回Ok内的值到变量username_file。如果发生错误? 操作符将提前从整个函数中返回并将任何Err值交给调用代码。同样的事情也适用于read_to_string调用结束时的? ? 运算符消除了大量的模板使这个函数的实现更加简单。我们甚至可以通过在? 后面紧跟的方法调用链来进一步缩短这段代码如下例8中所示。 例8文件名:src/main.rs use std::fs::File; use std::io::{self, Read};fn read_username_from_file() - ResultString, io::Error {let mut username String::new();File::open(hello.txt)?.read_to_string(mut username)?;Ok(username) } 我们把创建用username中的新String移到了函数的开头这部分没有改变。我们没有创建一个变量username_file而是将对read_to_string的调用直接链接到File::open(hello.txt)的结果上。我们在 read_to_string 调用的最后仍然有一个 ? 而且当 File::open和 read_to_string 都成功时我们仍然返回一个包含用户名的 Ok 值而不是返回错误。其功能与例6和例7中的相同这只是一种不同的、更符合人体工程学的写法而已。 例9显示了一种使用fs::read_to_string使其更短的方法。 例9文件名:src/main.rs use std::fs; use std::io;fn read_username_from_file() - ResultString, io::Error {fs::read_to_string(hello.txt) } 将文件读入字符串是一个相当常见的操作所以标准库提供了方便的fs::read_to_string函数该函数打开文件创建一个新的String读取文件的内容将内容放入该String中并返回它。当然使用fs::read_to_string并没有给我们解释所有错误处理的机会所以我们先用较长的方法来做。 哪些地方可以使用? 操作符 ? 操作符只能在返回类型与? 操作符所使用的值兼容的函数中使用。这是因为?操作符被定义为执行从函数中提前返回一个值其方式与我们在例6 中定义的match表达式相同。在清例6中match使用的是一个Result值而提前返回了一个Err(e)值。函数的返回类型必须是一个 Result这样才能与这个Return兼容。 在例10中让我们看看如果我们在一个main函数中使用? 操作符其返回类型与我们使用的值的类型不兼容我们会得到什么错误。 例10文件名:src/main.rs use std::fs::File;fn main() {let greeting_file File::open(hello.txt)?; } 这段代码打开了一个文件这可能会失败。? 操作符跟随File::open返回的结果值但这个main函数的返回类型是而不是Result。当我们编译这段代码时我们会得到以下错误信息。 这个错误指出我们只允许在返回 Result、Option 或其他实现 FromResidual 的类型的函数中使用 ? 操作符。 要解决这个错误你有两个选择。一种选择是改变你的函数的返回类型使之与你使用的? 运算符的值兼容只要你没有限制阻止这样做。另一种技术是使用match或ResultT, E方法之一以任何适当的方式处理ResultT, E。 该错误信息还提到? 也可以用于 OptionT值。与在Result上使用 ? 一样你只能在一个返回 Option 的函数中对 Option 使用 ? 。在 OptionT上调用 ? 操作符的行为与在 ResultT, E上调用的行为类似如果值是 NoneNone将在此时从函数中提前返回。如果值是SomeSome里面的值就是表达式的结果值函数继续。例11中有一个函数的例子它可以找到给定文本中第一行的最后一个字符。 例11 fn last_char_of_first_line(text: str) - Optionchar {text.lines().next()?.chars().last() } 这个函数返回Optionchar因为那里有可能有一个字符但也有可能没有。这段代码接收了文text字符串的切片参数并对其调用lines方法该方法返回字符串中的行的迭代器。因为这个函数想检查第一行所以它在迭代器上调用next从迭代器中获得第一个值。如果text是空字符串对next的调用将返回None在这种情况下我们用? 来停止并从last_char_of_first_line返回None。如果text不是空字符串next将返回一个Some值包含text中第一行的字符串切片。 ? 提取了字符串片段我们可以在该字符串片段上调用chars来获得其字符的迭代器。我们对这第一行的最后一个字符感兴趣所以我们调用last来返回迭代器中的最后一项。这是一个Option因为第一行有可能是空字符串例如如果text以空行开始但在其他行有字符如\nhi。然而如果第一行有最后一个字符它将在Some变体中被返回。中间的? 操作符给了我们一个简洁的方式来表达这个逻辑使我们可以在一行中实现这个函数。如果我们不能在 Option 上使用 ? 操作符我们就必须使用更多的方法调用或match表达式来实现这个逻辑。  请注意你可以在一个返回结果的函数中对一个Result使用 ? 操作符也可以在一个返回 Option 的函数中对一个 Option 使用 ? 操作符但是你不能混合匹配。运算符不会自动将一个Result转换为一个Option 反之亦然在这种情况下你可以使用像Result的ok方法或Option 的ok_or方法来进行明确的转换。 到目前为止我们所使用的所有main函数都返回。main函数很特别因为它是可执行程序的进入和退出点它的返回类型是有限制的以使程序的行为符合预期。 幸运的是mainmain返回一个Result(), E。清例12中有例子10的代码但我们将main的返回类型改为Result(), Boxdyn Error并在结尾处添加了一个返回值Ok(())。这段代码现在可以编译了。 例12 use std::error::Error; use std::fs::File;fn main() - Result(), Boxdyn Error {let greeting_file File::open(hello.txt)?;Ok(()) } Boxdyn Error类型是一个特质对象我们将在后面章节的 使用允许不同类型的值的特质对象 一节中讨论这个问题。现在你可以把Boxdyn Error理解为 任何类型的错误。在错误类型为Boxdyn Error的main函数中对Result值使用? 是允许的因为它允许任何Err值被提前返回。即使这个main函数的主体只返回std::io::Error类型的错误通过指定Boxdyn Error即使有更多返回其他错误的代码被添加到main的主体中这个签名仍然是正确的。 当main函数返回一个Result(), E时如果main返回Ok(())可执行程序将以0的值退出如果main返回Err值则以非零值退出。用C语言编写的可执行文件在退出时返回整数成功退出的程序返回整数0出错的程序返回0以外的某个整数。 main函数可以返回任何实现std::process::Termination trait的类型它包含一个返回ExitCode的函数report。关于为你自己的类型实现Termination特性的更多信息请查阅标准库文档。 现在我们已经讨论了调用panic或返回Result的细节让我们回到如何决定在什么情况下使用哪种方法是合适的话题。 本章重点 带结果的可恢复错误概念和使用不同错误的匹配程序死掉的方式unwrap和expect传播误差的概念?操作符的使用?操作符的使用场景
http://www.dnsts.com.cn/news/62814.html

相关文章:

  • 企业网站推广方法有哪些?合肥网站建设电话咨询
  • 电话手表网站做的烂的大网站
  • 如何把自己网站推广出去一般通过是什么梗
  • 做网站如何网站考虑优化广州seo优化公司
  • 皮革城网站建设方案筑易设计网
  • 淘掌门官方网站wordpress主题在线编辑器
  • jsp做的网站源码wordpress网站go.php跳转
  • 陕西省建设网站 五大员过期网址域名注册查询
  • 给国外做网站福州seo招聘
  • 如何做一间公司的网站seoul是韩国哪个城市
  • 深圳制作网站的公司简介wordpress外观插件
  • 企业网站网页打开慢服装设计公司效果图
  • 如何创网站网站建设需要多钱
  • 公司网站建设包括如何用网站做推广
  • 北京网站建设58山东住房和城乡建设厅网站登陆
  • 怎么找做网站平台公司高端网站的建设
  • 苏州网站建设网站网页美工设计(第2版)
  • 拖曳式网站建设ps中网站页面做多大的
  • 做网站必须用域名吗wordpress文件上传类型
  • 电脑上如何做网站宣传村镇建设年度报表登录网站
  • 个人电脑做网站服务器教程太原做网站要多少钱呢
  • 网站推广问题如何查询网站打开速度变慢
  • 免费建社交网站重庆网站建设yunhuit
  • 玉林市建设工程交易中心网站个人网页生成器
  • 温州网站建设对比网页小游戏怎么下载
  • 榆林市城乡建设规划网站衡阳网站建设怎样收费
  • wp网站源码家装设计师培训学校学费
  • 建设厅职业资格中心网站网站费用
  • wordpress 加载很慢seo排名价格
  • 网站及微站建设合同验收网站建设公司郑州