学习Rust的朋友可能经常看到Result和Option,虽然不一定直接看到他们本身,但是他们的方法还是常见的,比如:xxx.ok().expect(“…”);
这个xxx一般就是某个函数返回的Result类型了,下面就详细的讲解下他们的来源
现在看看rust book里的那个guess game,有这么一段:
http://doc.rust-lang.org/book/guessing-game.html
<code class="hljs rust has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">use</span> std::io;
<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(</span>) {
println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Guess the number!"</span>);
println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Please input your guess."</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> guess = String::new();
io::stdin().read_line(&<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> guess)
.ok()
.expect(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Failed to read line"</span>);
println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"You guessed: {}"</span>, guess);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>
前面几行都好理解,我们看看10~12行的几个ok,expect到底是什么
理解这些内容最好的方法就是看源代码,不过大家别慌,不是要你从头开始啃rust所有源码,只需要有针对性的看就可以了
大家记住下面这个常用的链接,这儿可以查到rust的所有源代码,可以搜索,反应速度非常快:
https://doc.rust-lang.org/std/
1、io::stdin()
现在从头开始,先看io::stdin()这个是什么
这个网页的最上方就是输入框了,我们一步步来,先输入 io::stdin
注意:不要加后面括号
下面就是搜索的结果,可以看到第二行就是我们要找的函数(第一行是结构体,我们要找的是函数)
点击进去就可以查看源代码了,这个函数声明很简单,只是返回了一个Stdin的结构体
如果想看源代码就点右上角的那个src,见上图右上角红色框
我们现在不需要去看源代码了,现在看看Stdin的介绍就可以了,看图上左边的红色框里的Stdin是可以点击的,点进去然后找到read_line方法:
<code class="hljs oxygene has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">fn read_line(&mut <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>, buf: &mut String) -> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Result</span><usize>[−]
Locks this handle <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> reads a line <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span> input <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">into</span> the specified buffer.
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">For</span> detailed semantics <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span> this <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">method</span>, <span class="hljs-title" style="box-sizing: border-box;">see</span> <span class="hljs-title" style="box-sizing: border-box;">the</span> <span class="hljs-title" style="box-sizing: border-box;">documentation</span> <span class="hljs-title" style="box-sizing: border-box;">on</span> <span class="hljs-title" style="box-sizing: border-box;">BufRead</span>:</span>:read_line.</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
上面是read_line的介绍,我们不去关心他的实现过程了,先看看他返回的类型是:
<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Result<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">usize</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
2、Result
点进去看看Result的页面,这个就是这篇blog的重点了
<code class="hljs oxygene has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">type</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Result</span><T> = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Result</span><T, Error>;
A <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">type</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> results generated <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">by</span> I/O related functions <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">where</span> the Err <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">type</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> hard-wired <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> io::Error.
This typedef <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> generally used <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> avoid writing <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">out</span> io::Error directly <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> otherwise a direct mapping <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> std::<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">result</span>::<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Result</span>.</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
上面的介绍部分说的是io::Result其实是为了书写方便定义的,他用io::Error类型替代了std::result::Result<T,Error>
里的Error类型
这样io::Result比std::result::Result更加具体化了,那么写起来也相对简单了,他只可能返回io::Error类型的错误
因为这儿io::Result只是个类型定义,所以我们要去看std::result::Result的源代码,搜索过程就不详述了,具体看源码:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">pub <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">enum</span> Result<T, E> {
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><span class="hljs-xmlDocTag" style="box-sizing: border-box;">///</span> Contains the success value</span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#[stable(feature = "rust1", since = "1.0.0")]</span>
Ok(T),
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><span class="hljs-xmlDocTag" style="box-sizing: border-box;">///</span> Contains the error value</span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#[stable(feature = "rust1", since = "1.0.0")]</span>
Err(E)
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
上面就是定义了,可以看到他是个enum,有OK和Err类型,分别对应了Result泛型里的类型T和E,std::result::Result里并没有限制E和T的类型,但是io::Result就把E的类型限制成了io::Error,这个大家注意下就好
说了这么多我们再看看问题
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-label" style="box-sizing: border-box;">io:</span>:stdin()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.read</span>_line(&mut guess)
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ok</span>()
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.expect</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Failed to read line"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
刚才我们确认了read_line返回的是io::Result<T>
类型,那么ok()函数肯定就是Result的一个方法了,继续看std::result::Result的方法实现的源代码:
<code class="hljs coffeescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> pub fn ok<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span> -></span> Option<T> {
match self {
Ok<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(x)</span> =></span> Some(x),
Err<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(_)</span> =></span> None,
}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
3、Option
可以看到ok函数返回的是Option<T>
,还是没有返回我们最终想要的类型T,我们还是先看看ok的代码吧。
其实这个函数非常简单,就是一个match,如果没有出错用Option::Some把我们要的数据用包装下返回;如果出错了就返回Option::None
这样皮球又提到了Option去了…我们再继续查Option:
<code class="hljs rust has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">pub</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">enum</span> <span class="hljs-title" style="box-sizing: border-box;">Option</span><T> {
None,
Some(T),
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
上面就是Option的定义,也是个enum。其中None顾名思义就是“没有”,他没有包装类型T,所以他真的什么都没。Some带来我们的类型T,所以现在目标已经很静了,只要把T对应的数据弄出来就最终得到了我们要的数据了
继续看这个代码,ok()返回的是Option,那么expect肯定就是Option的方法了
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-label" style="box-sizing: border-box;">io:</span>:stdin()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.read</span>_line(&mut guess)
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ok</span>()
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.expect</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Failed to read line"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
继续看Option源代码,看他方法的实现:
<code class="hljs rust has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">pub</span> <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">expect</span>(</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>, msg: &<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">str</span>) -> T {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">match</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> {
Some(val) => val,
None => panic!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span>, msg),
}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
终于看到想要的返回类型了:T,这个就是我们最终要的数据了,看read_line返回的是io::Result<usize>
,所以这儿返回的是一个uszie类型的长度,不过guess game里并没有使用他
可以看到这个函数也是个match,如果是Some能匹配了就把他携带的数据返回;如果是None类型说明这个Option根本就没携带数据,也就是前面的Result出错了,所以会调用panic!宏把你传递进去的字符串打印出来并且退出程序。
4、其他写法
现在绕了一大圈终于找到T了,其实ok().expect(…);这种只是偷懒的写法,出错了直接打印你的字符串就退出程序了。当然有更偷懒的,看std::result::Result的代码:
<code class="hljs coffeescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">pub fn <span class="KSFIND_CLASS_SELECT" id="0KSFindDIV" style="text-align: center; -webkit-box-shadow: rgba(0, 0, 0, 0.74902) 0px 1px 3px; border: 0px solid rgb(239, 210, 0); visibility: visible !important; bottom: 0px !important; left: 0px !important; right: 0px !important; top: 0px !important; height: inherit !important; width: inherit !important; float: none !important; color: black !important; display: inline !important; padding-bottom: 1px !important; padding-top: 2px !important; position: relative !important; z-index: 3000050 !important; border-radius: 3px !important; box-sizing: border-box; background: none 0px 0px repeat scroll rgb(239, 210, 0) !important;">unwrap</span><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span> -></span> T {
match self {
Ok<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(t)</span> =></span> t,
Err<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(e)</span> =></span>
panic!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"called `Result::<span class="KSFIND_CLASS" id="1KSFindDIV" style="text-align: center; -webkit-box-shadow: rgba(0, 0, 0, 0.74902) 0px 1px 3px; bottom: 0px !important; left: 0px !important; right: 0px !important; top: 0px !important; height: inherit !important; width: inherit !important; float: none !important; color: black !important; padding: 2px 0px 1px !important; display: inline !important; position: relative !important; z-index: 3000000 !important; box-sizing: border-box; background: none 0px 0px repeat scroll rgb(255, 244, 151) !important;">unwrap</span>()` on an `Err` value: {:?}"</span>, e)
}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>
那么代码就可以写成下面这样就可以了:
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-label" style="box-sizing: border-box;">io:</span>:stdin()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.read</span>_line(&mut guess)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.<span class="KSFIND_CLASS" id="2KSFindDIV" style="text-align: center; -webkit-box-shadow: rgba(0, 0, 0, 0.74902) 0px 1px 3px; box-sizing: border-box; bottom: 0px !important; left: 0px !important; right: 0px !important; top: 0px !important; height: inherit !important; width: inherit !important; float: none !important; padding: 2px 0px 1px !important; display: inline !important; position: relative !important; z-index: 3000000 !important; background: none 0px 0px repeat scroll rgb(255, 244, 151) !important;">unwrap</span></span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
这个是非常不建议的用法,除非你非常肯定read_line不可能出错
虽然这个read_line结果我们并没有使用,但是还是需要处理一下,不然Result没有处理编译器会给警告的
处理result最直接和直观的方法就是直接match,不需要通过Option中转了:
<code class="hljs coffeescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">match <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(0, 136, 0);">io</span>::stdin().read_line(&mut guess) {
Ok<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(size)</span>=></span>xxxx,
Err<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(e)</span>=></span>xxx,
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
xxx处换成你自己的代码就可以了