折腾了半天,终于要开始写 I/O 了。首当其冲的是一个 TCP 服务端 socket:segmentfault
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
上:socket
use std::io::net::tcp; use std::io::net::ip::{SocketAddr, Ipv4Addr};
起初我只是这样写了这么两句,没想到官方文档抄来的代码竟然编译出错了:tcp
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()
确实说不过去。函数
可是为何文档里的例子这么写呢?spa
原来我漏掉了一句 use
:code
use std::io::{Acceptor, Listener};
虽然是没有地方直接用到他们,可是自从加上这两个以后,编译就神奇的经过啦!htm
仍是得看文档。人家说了,这是由于 I/O 操做常常会出错,为了不通篇的处理 IoResult
,特地制做的这种方便用法——能够不手动解包 IoResult
而直接看成成功结果来使用,只是须要 use
std::io
下面的一些东西。blog
这是怎么作到的?!ip
原来这里的猫腻都在 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 要不要也照猫画虎这么搞,貌似很省事儿哦。