Rust 語言學習筆記(三)

(一)在這裏,(二)在這裏,下面是(三)。html

神奇的 I/O 異常

折騰了半天,終於要開始寫 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

原來我漏掉了一句 usecode

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 要不要也照貓畫虎這麼搞,貌似很省事兒哦。

相關文章
相關標籤/搜索