折騰了半天,終於要開始寫 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 要不要也照貓畫虎這麼搞,貌似很省事兒哦。