神奇的 I/O 异常
折腾了半天,终于要开始写 I/O 了。首当其冲的是一个 TCP 服务端 socket:
impl TcpListener {
pub fn set_address(&self, address: &str) {
let addr = from_str::<SocketAddr>(address).unwrap();
let listener = tcp::TcpListener::bind(addr);
let mut acceptor = listener.listen();
for stream in acceptor.incoming() {
spawn(proc() {
});
}
drop(acceptor);
}
}
其实这段程序没什么神奇的啦,神奇的事情出现在 use
上:
use std::io::net::tcp;
use std::io::net::ip::{SocketAddr, Ipv4Addr};
起初我只是这样写了这么两句,没想到官方文档抄来的代码居然编译出错了:
tcp_listener.rs:16:28: 16:45 error: type `std::result::Result<std::io::net::tcp::TcpListener,std::io::IoError>` does not implement any method in scope named `listen`
tcp_listener.rs:16 let mut acceptor = listener.listen();
^~~~~~~~~~~~~~~~~
error: aborting due to previous error
参考出错信息,查阅了一下源码,人家 bind()
返回的确实是一个 Result
,这么生猛地直接调用 listen()
确实说不过去。
但是为什么文档里的例子这么写呢?
原来我漏掉了一句 use
:
use std::io::{Acceptor, Listener};
虽然是没有地方直接用到他们,但是自从加上这两个之后,编译就神奇的通过啦!
还是得看文档。人家说了,这是因为 I/O 操作经常会出错,为了避免通篇的处理 IoResult
,特意制作的这种方便用法——可以不手动解包 IoResult
而直接当作成功结果来使用,只是需要 use
std::io
下面的一些东西。
这是怎么做到的?!
原来这里的猫腻都在 libstd/io/result.rs
里面。比如刚才碰到的 Listener
这个:
impl<T, A: Acceptor<T>, L: Listener<T, A>> Listener<T, A> for IoResult<L> {
fn listen(self) -> IoResult<A> {
match self {
Ok(listener) => listener.listen(),
Err(e) => Err(e),
}
}
}
哈!Rust 还能这么搞!生生给 IoResult<Listener...>
包了一个函数进去,怪不得可以直接调用 listen
了呢。于是,我默默地想,zmq.rs 要不要也照猫画虎这么搞,貌似很省事儿哦。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。