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

做教学的视频网站网站推广外链

做教学的视频网站,网站推广外链,wordpress高校主题,组工网站建设方案目录 1、用 Result 处理可恢复的错误 1.1 传播错误的简写#xff1a;? 运算符 1.2 哪里可以使用 ? 运算符 2、要不要 panic! 2.1 示例、代码原型和测试都非常适合 panic 2.2 当我们比编译器知道更多的情况 2.3 错误处理指导原则 2.4 创建自定义类型进行有效性验证 …目录 1、用 Result 处理可恢复的错误 1.1 传播错误的简写? 运算符 1.2 哪里可以使用 ? 运算符 2、要不要 panic! 2.1 示例、代码原型和测试都非常适合 panic 2.2 当我们比编译器知道更多的情况 2.3 错误处理指导原则 2.4 创建自定义类型进行有效性验证 2.5 总结 1、用 Result 处理可恢复的错误 1.1 传播错误的简写? 运算符 先看下如下示例 fn main() {fn read_file() - ResultString, io::Error {let file_result File::open(hello.txt);let mut v String::new();file_result.unwrap().read_to_string(mut v)?;Ok(v)}let res read_file();print!({:?}, res) } Result 值之后的 ? 被定义为之前的处理 Result 值的 match 表达式有着完全相同的工作方式。如果 Result 的值是 Ok这个表达式将会返回 Ok 中的值而程序将继续执行。如果值是 ErrErr 将作为整个函数的返回值就好像使用了 return 关键字一样这样错误值就被传播给了调用者。 之前示例的 match 表达式与 ? 运算符所做的有一点不同? 运算符所使用的错误值被传递给了 from 函数它定义于标准库的 From trait 中其用来将错误从一种类型转换为另一种类型。当 ? 运算符调用 from 函数时收到的错误类型被转换为由当前函数返回类型所指定的错误类型。这在当函数返回单个错误类型来代表所有可能失败的方式时很有用即使其可能会因很多种原因失败。 ? 运算符消除了大量样板代码并使得函数的实现更简单。我们甚至可以在 ? 之后直接使用链式方法调用来进一步缩短代码如下所示 fn main() {fn read_file() - ResultString, io::Error {let mut v String::new();let _ File::open(hello.txt)?.read_to_string(mut v)?;Ok(v)}let res read_file();print!({:?}, res) } 以下代码展示了一个使用 fs::read_to_string 的更为简短的写法 fn main() {fn read_file() - ResultString, io::Error {fs::read_to_string(hello1.txt)}let res read_file();print!({:?}, res) } 将文件读取到一个字符串是相当常见的操作所以 Rust 提供了名为 fs::read_to_string 的函数它会打开文件、新建一个 String、读取文件的内容并将内容放入 String接着返回它。当然这样做就没有展示所有这些错误处理的机会了. 1.2 哪里可以使用 ? 运算符 ? 运算符只能被用于返回值与 ? 作用的值相兼容的函数。因为 ? 运算符被定义为从函数中提早返回一个值这与之前示例的 match 表达式有着完全相同的工作方式。示例中 match 作用于一个 Result 值提早返回的分支返回了一个 Err(e) 值。函数的返回值必须是 Result 才能与这个 return 相兼容。 让我们看看在返回值不兼容的 main 函数中使用 ? 运算符会得到什么错误 fn main() {fs::read_to_string(hello1.txt)?; } 这段代码打开一个文件这可能会失败。? 运算符作用于 File::open 返回的 Result 值不过 main 函数的返回类型是 () 而不是 Result。当编译这些代码会得到如下错误信息  这个错误指出只能在返回 Result 或者其它实现了 FromResidual 的类型的函数中使用 ? 运算符。 为了修复这个错误有两个选择。一个是如果没有限制的话将函数的返回值改为 ResultT, E。另一个是使用 match 或 ResultT, E 的方法中合适的一个来处理 ResultT, E。 错误信息也提到 ? 也可用于 OptionT 值。如同对 Result 使用 ? 一样只能在返回 Option 的函数中对 Option 使用 ?。在 OptionT 上调用 ? 运算符的行为与 ResultT, E 类似如果值是 None此时 None 会从函数中提前返回。如果值是 SomeSome 中的值作为表达式的返回值同时函数继续。 文本中返回第一行最后一个字符的函数的例子 fn last_char_of_first_line(text: str) - Optionchar {text.lines().next()?.chars().last()} 这个函数返回 Optionchar 因为它可能会在这个位置找到一个字符也可能没有字符。这段代码获取 text 字符串 slice 作为参数并调用其 lines 方法这会返回一个字符串中每一行的迭代器。因为函数希望检查第一行所以调用了迭代器 next 来获取迭代器中第一个值。如果 text 是空字符串next 调用会返回 None此时我们可以使用 ? 来停止并从 last_char_of_first_line 返回 None。如果 text 不是空字符串next 会返回一个包含 text 中第一行的字符串 slice 的 Some 值。 ? 会提取这个字符串 slice然后可以在字符串 slice 上调用 chars 来获取字符的迭代器。我们感兴趣的是第一行的最后一个字符所以可以调用 last 来返回迭代器的最后一项。这是一个 Option因为有可能第一行是一个空字符串例如 text 以一个空行开头而后面的行有文本像是 \nhi。不过如果第一行有最后一个字符它会返回在一个 Some 成员中。? 运算符作用于其中给了我们一个简洁的表达这种逻辑的方式。如果我们不能在 Option 上使用 ? 运算符则不得不使用更多的方法调用或者 match 表达式来实现这些逻辑。 注意你可以在返回 Result 的函数中对 Result 使用 ? 运算符可以在返回 Option 的函数中对 Option 使用 ? 运算符但是不可以混合搭配。? 运算符不会自动将 Result 转化为 Option反之亦然在这些情况下可以使用类似 Result 的 ok 方法或者 Option 的 ok_or 方法来显式转换。 目前为止我们所使用的所有 main 函数都返回 ()。main 函数是特殊的因为它是可执行程序的入口点和退出点为了使程序能正常工作其可以返回的类型是有限制的。 幸运的是 main 函数也可以返回 Result(), E以下示例 main 的返回值为 Result(), Boxdyn Error 并在结尾增加了一个 Ok(()) 作为返回值。这段代码可以编译 fn main() - Result(), Boxdyn Error {let greeting_file File::open(hello1.txt)?;Ok(()) } Boxdyn Error 类型是一个 trait 对象trait object 目前可以将 Boxdyn Error 理解为 “任何类型的错误”。在返回 Boxdyn Error 错误类型 main 函数中对 Result 使用 ? 是允许的因为它允许任何 Err 值提前返回。即便 main 函数体从来只会返回 std::io::Error 错误类型通过指定 Boxdyn Error这个签名也仍是正确的甚至当 main 函数体中增加更多返回其他错误类型的代码时也是如此。 当 main 函数返回 Result(), E如果 main 返回 Ok(()) 可执行程序会以 0 值退出而如果 main 返回 Err 值则会以非零值退出成功退出的程序会返回整数 0运行错误的程序会返回非 0 的整数。Rust 也会从二进制程序中返回与这个惯例相兼容的整数。 main 函数也可以返回任何实现了 std::process::Termination trait 的类型它包含了一个返回 ExitCode 的 report 函数。 2、要不要 panic! 那么该如何决定何时应该 panic! 以及何时应该返回 Result 呢如果代码 panic就没有恢复的可能。你可以选择对任何错误场景都调用 panic!不管是否有可能恢复不过这样就是你代替调用者决定了这是不可恢复的。选择返回 Result 值的话就将选择权交给了调用者而不是代替他们做出决定。调用者可能会选择以符合他们场景的方式尝试恢复或者也可能干脆就认为 Err 是不可恢复的所以他们也可能会调用 panic! 并将可恢复的错误变成了不可恢复的错误。因此返回 Result 是定义可能会失败的函数的一个好的默认选择。 在一些类似示例、原型代码prototype code和测试中panic 比返回 Result 更为合适不过它们并不常见。让我们讨论一下为何在示例、代码原型和测试中以及那些人们认为不会失败而编译器不这么看的情况下panic 是合适的。 2.1 示例、代码原型和测试都非常适合 panic 当你编写一个示例来展示一些概念时在拥有健壮的错误处理代码的同时也会使得例子不那么明确。例如调用一个类似 unwrap 这样可能 panic! 的方法可以被理解为一个你实际希望程序处理错误方式的占位符它根据其余代码运行方式可能会各不相同。 类似地在我们准备好决定如何处理错误之前unwrap和expect方法在原型设计时非常方便。当我们准备好让程序更加健壮时它们会在代码中留下清晰的标记。 如果方法调用在测试中失败了我们希望这个测试都失败即便这个方法并不是需要测试的功能。因为 panic! 会将测试标记为失败此时调用 unwrap 或 expect 是恰当的。 2.2 当我们比编译器知道更多的情况 当你有一些其他的逻辑来确保 Result 会是 Ok 值时调用 unwrap 或者 expect 也是合适的虽然编译器无法理解这种逻辑。你仍然需要处理一个 Result 值即使在你的特定情况下逻辑上是不可能的你所调用的任何操作仍然有可能失败。如果通过人工检查代码来确保永远也不会出现 Err 值那么调用 unwrap 也是完全可以接受的这里是一个例子 fn main() {let home: IpAddr 127.0.0.1111.parse().expect(IP address error......);panic!({:?}, home) } 我们通过解析一个硬编码的字符来创建一个 IpAddr 实例。可以看出 127.0.0.1 是一个有效的 IP 地址所以这里使用 expect 是可以接受的。然而拥有一个硬编码的有效的字符串也不能改变 parse 方法的返回值类型它仍然是一个 Result 值而编译器仍然会要求我们处理这个 Result好像还是有可能出现 Err 成员那样。这是因为编译器还没有智能到可以识别出这个字符串总是一个有效的 IP 地址。如果 IP 地址字符串来源于用户而不是硬编码进程序中的话那么就 确实 有失败的可能性这时就绝对需要我们以一种更健壮的方式处理 Result 了。提及这个 IP 地址是硬编码的假设会促使我们将来把 expect 替换为更好的错误处理我们应该从其它代码获取 IP 地址。 2.3 错误处理指导原则 在当有可能会导致有害状态的情况下建议使用 panic! —— 在这里有害状态是指当一些假设、保证、协议或不可变性被打破的状态例如无效的值、自相矛盾的值或者被传递了不存在的值 —— 外加如下几种情况 有害状态是非预期的行为与偶尔会发生的行为相对比如用户输入了错误格式的数据。在此之后代码的运行依赖于不处于这种有害状态而不是在每一步都检查是否有问题。没有可行的手段来将有害状态信息编码进所使用的类型中的情况。 如果别人调用你的代码并传递了一个没有意义的值尽最大可能返回一个错误如此库的用户就可以决定在这种情况下该如何处理。然而在继续执行代码是不安全或有害的情况下最好的选择可能是调用 panic! 并警告库的用户他们的代码中有 bug这样他们就会在开发时进行修复。类似的如果你正在调用不受你控制的外部代码并且它返回了一个你无法修复的无效状态那么 panic! 往往是合适的。 然而当错误预期会出现时返回 Result 仍要比调用 panic! 更为合适。这样的例子包括解析器接收到格式错误的数据或者 HTTP 请求返回了一个表明触发了限流的状态。在这些例子中应该通过返回 Result 来表明失败预期是可能的这样将有害状态向上传播调用者就可以决定该如何处理这个问题。使用 panic! 来处理这些情况就不是最好的选择。 当你的代码在进行一个使用无效值进行调用时可能将用户置于风险中的操作时代码应该首先验证值是有效的并在其无效时 panic!。这主要是出于安全的原因尝试操作无效数据会暴露代码漏洞这就是标准库在尝试越界访问数组时会 panic! 的主要原因尝试访问不属于当前数据结构的内存是一个常见的安全隐患。函数通常都遵循 契约contracts它们的行为只有在输入满足特定条件时才能得到保证。当违反契约时 panic 是有道理的因为这通常代表调用方的 bug而且这也不是那种你希望所调用的代码必须处理的错误。事实上所调用的代码也没有合理的方式来恢复而是需要调用方的 程序员 修复其代码。函数的契约尤其是当违反它会造成 panic 的契约应该在函数的 API 文档中得到解释。 虽然在所有函数中都拥有许多错误检查是冗长而烦人的。幸运的是可以利用 Rust 的类型系统以及编译器的类型检查为你进行很多检查。如果函数有一个特定类型的参数可以在知晓编译器已经确保其拥有一个有效值的前提下进行你的代码逻辑。例如如果你使用了一个并不是 Option 的类型则程序期望它是 有值 的并且不是 空值。你的代码无需处理 Some 和 None 这两种情况它只会有一种情况就是绝对会有一个值。尝试向函数传递空值的代码甚至根本不能编译所以你的函数在运行时没有必要判空。另外一个例子是使用像 u32 这样的无符号整型也会确保它永远不为负。 2.4 创建自定义类型进行有效性验证 让我们使用 Rust 类型系统的思想来进一步确保值的有效性并尝试创建一个自定义类型以进行验证。回忆一下第二章的猜猜看游戏我们的代码要求用户猜测一个 1 到 100 之间的数字在将其与秘密数字做比较之前我们从未验证用户的猜测是位于这两个数字之间的我们只验证它是否为正。在这种情况下其影响并不是很严重“Too high” 或 “Too low” 的输出仍然是正确的。但是这是一个很好的引导用户得出有效猜测的辅助例如当用户猜测一个超出范围的数字或者输入字母时采取不同的行为。 一种实现方式是将猜测解析成 i32 而不仅仅是 u32来默许输入负数接着检查数字是否在范围内 loop {// --snip--let guess: i32 match guess.trim().parse() {Ok(num) num,Err(_) continue,};if guess 1 || guess 100 {println!(The secret number will be between 1 and 100.);continue;}match guess.cmp(secret_number) {// --snip--} 2.5 总结 Rust 的错误处理功能被设计为帮助你编写更加健壮的代码。panic! 宏代表一个程序无法处理的状态并停止执行而不是使用无效或不正确的值继续处理。Rust 类型系统的 Result 枚举代表操作可能会在一种可以恢复的情况下失败。可以使用 Result 来告诉代码调用者他需要处理潜在的成功或失败。在适当的场景使用 panic! 和 Result 将会使你的代码在面对不可避免的错误时显得更加可靠。
http://www.pierceye.com/news/86645/

相关文章:

  • 网站手机网站怎么建立关于建设学校网站的报告书
  • 做网站工作描述网络怎么推广
  • 麻涌镇网站建设网站小空间
  • 网站推广策划的策略咨询行业网站开发
  • 做我女朋友的套路网站阜宁网站开发
  • 宁夏做网站的wordpress 分页制作
  • 求推荐专门做借条的网站网站建设以推广
  • 12306网站做的好还是百度做的好网络设计的目的
  • 红酒哪个网站做的好医药公司网站设计
  • 绍兴seo网站管理wordpress目录和页面
  • 网站建设人员招聘seo是指什么岗位
  • 单页网站排名优化建设股票交易网站
  • 自己做博客网站互联网公司市值排名城市
  • 李沧区网站服务公司网站首页包含的内容怎么做
  • 做 个收废品网站wordpress变装博客
  • 手机网站建设视频教程_wordpress后台504
  • 长沙网站公司网站建设唐山做网站那家好
  • 顺德公司做网站语言互动网站建设
  • 静态网页模板生成工具汨罗网站seo
  • 做网站前端用什么网站要不要备案
  • 手机网站开放南通物流网站建设
  • 公司网站制作需要什么微信小程序 网站建设
  • 莆田哪里有学做网站的深圳本地网站建设
  • 企业品牌网站建设公司门户网站域名
  • 做seo是要先有网站吗网站模板首页
  • 建设网站用英文怎么说在线app制作平台
  • 网站开发技术的选择网站做点击收费
  • 商务网站规划与设计品牌建设的本质英语作文
  • 陕西西安网站建设公司排名深圳建站公司有推荐的公司吗
  • 网站app封装怎么做怎么把网站上传到域名