乘着打盹的時間看了一眼前兩天寫的日期轉換的開源工具: ts。發現管道 pipeline
的功能點能夠放大一下, 就此記錄一下以備未來只需。git
但凡在類 Unix 系統上敲過命令的人,大多使用過管道功能. 所謂管道,就是將A程序的標準輸出做爲B程序的標準輸入。而在類 Unix 系統只須要使用 |
符號,鏈接 A 和 B 程序便可, 即 A | B
。經過屢次管道鏈接,就能夠實現很是強大的功能。因此在類 Unix 系統上開發命令行程序有個著名的原則: KISS
,即 Keep It Simple Stupid。github
畫了張簡單的圖:segmentfault
在 Go 程序中實現管道功能及其簡單,直接上碼:工具
//先取程序的標準輸入屬性信息 info, err := os.Stdin.Stat() if err != nil { return errors.Annotate(err, "stdin stat failed") } // 判斷標準輸入設備屬性 os.ModeCharDevice 是否設置 // 同時判斷是否有數據輸入 if (info.Mode()&os.ModeCharDevice) == os.ModeCharDevice && info.Size() > 0 { bytes, err := ioutil.ReadAll(os.Stdin) if err != nil { return errors.Annotate(err, "stdin read failed") } //TODO... }
屬性 os.ModeCharDevice
的意思是標準輸入的設備類型是Unix字節流設備(Unix character device)即終端(terminal)輸入。該方式判斷有一個注意點:spa
須要判斷info.Size()
, 即標準輸入是有數據輸入的。若是終端沒有輸入的話,程序會在ioutil.ReadAll
處阻塞。
因此使用這種方式須要瞭解不一樣條件設置的用途,請結合實際開發需求。除了這個方式之外,還有另外更加簡單的實現方法:命令行
// 直接判斷 標準輸入屬性是否設置 os.ModeNamedPipe 便可 if (info.Mode()&os.ModeNamedPipe) == os.ModeNamedPipe { //TODO... }
標準輸入只有在存在輸入的時候,纔會設置os.ModeNamedPipe
屬性。相比較第一種方式,這種方式代碼更加簡單。只是命名管道(NamedPipe)又來了一個新概念,增長了理解的難度。引入一個 Linux 命令mkfifo
,這個命令就是建立命名管道用的。至於爲何這裏程序的os.Stdin
屬性會是os.ModeNamedPipe
,我這先偷個懶了。3d