在這章中將介紹 Go 中與外部通訊的通訊模塊。將會了解文件、目錄、網(wǎng)絡(luò)通訊和運(yùn)行其他程序。Go 的 I/O 核心是接口 io.Reader 和 io.Writer。
在 Go 中,從文件讀?。ɑ?qū)懭耄┦欠浅H菀椎?。程序只需要使?os 包就可以從文件 /etc/passwd 中讀取數(shù)據(jù)。
http://wiki.jikexueyuan.com/project/learn-go-language/images/178.png" alt="pic" />
接下來展示了如何做到這點:
如果想要使用緩沖 IO,則有 bufio 包:
http://wiki.jikexueyuan.com/project/learn-go-language/images/179.png" alt="pic" />
0 .打開文件;
轉(zhuǎn)換 f 為有緩沖的 Reader。NewReader 需要一個 io.Reader,因此或許你認(rèn)為這會出錯。但其實不會。任何有 Read() 函數(shù)就實現(xiàn)了這個接口。同時,從列表 7.1可以看到,*os.File 已經(jīng)這樣做了;
在前面已經(jīng)提到 io.Reader 接口對于 Go 語言來說非常重要。許多(如果不是全部的話)函數(shù)需要通過 io.Reader 讀取一些數(shù)據(jù)作為輸入。為了滿足這個接口,只需要實現(xiàn)一個方法:Read(p []byte) (n int, err error)。寫入則是(你可能已經(jīng)猜到了)實現(xiàn)了 Write 方法的 io.Writer。如果你讓自己的程序或者包中的類型實現(xiàn)了 io.Reader 或者 io.Writer 接口,那么整個 Go 標(biāo)準(zhǔn)庫都可以使用這個類型!
前面的程序?qū)⒄麄€文件讀出,但是通常情況下會希望一行一行的讀取。下面的片段展示了如何實現(xiàn):
http://wiki.jikexueyuan.com/project/learn-go-language/images/180.png" alt="pic" />
更加通用(但是也更加復(fù)雜)的方法是 ReadLine,參閱包 bufio 的文檔了解更多內(nèi)容。
在 shell 腳本中通常遇到的場景是需要檢查某個目錄是否存在,如果不存在,就創(chuàng)建一個。
http://wiki.jikexueyuan.com/project/learn-go-language/images/181.png" alt="pic" />
這兩個例子的相似之處展示了 Go 擁有的“腳本” 化特性,例如,用 Go 編寫程序感覺上類似使用動態(tài)語言(Python、Ruby、Perl 或者 PHP)。
來自命令行的參數(shù)在程序中通過字符串 slice os.Args 獲取,導(dǎo)入包 os 即可。flag 包有著精巧的接口,同樣提供了解析標(biāo)識的方法。這個例子是一個 DNS 查詢工具:
http://wiki.jikexueyuan.com/project/learn-go-language/images/182.png" alt="pic" />
0 .定義 bool 標(biāo)識,-dnssec。變量必須是指針,否則 package 無法設(shè)置其值;
當(dāng)參數(shù)被解析之后,就可以使用它們:
http://wiki.jikexueyuan.com/project/learn-go-language/images/183.png" alt="pic" />
os/exec 包有函數(shù)可以執(zhí)行外部命令,這也是在 Go 中主要的執(zhí)行命令的方法。通過定義一個有著數(shù)個方法的*exec.Cmd 結(jié)構(gòu)來使用。
執(zhí)行 ls -l:
import "os/exec"
cmd := exec.Command("/bin/ls", "-l")
err := cmd.Run()
上面的例子運(yùn)行了 “l(fā)s -l”,但是沒有對其返回的數(shù)據(jù)進(jìn)行任何處理,通過如下方法從命令行的標(biāo)準(zhǔn)輸出中獲得信息:
http://wiki.jikexueyuan.com/project/learn-go-language/images/184.png" alt="pic" />
所有網(wǎng)絡(luò)相關(guān)的類型和函數(shù)可以在 net 包中找到。這其中最重要的函數(shù)是 Dial。當(dāng) Dial 到遠(yuǎn)程系統(tǒng),這個函數(shù)返回 Conn 接口類型,可以用于發(fā)送或接收信息。函數(shù) Dial 簡潔的抽象了網(wǎng)絡(luò)層和傳輸層。因此 IPv4 或者 IPv6,TCP 或者 UDP 可以共用一個接口。
通過 TCP 連接到遠(yuǎn)程系統(tǒng)(端口 80),然后是 UDP,最后是 TCP 通過 IPv6,大致是這樣:
http://wiki.jikexueyuan.com/project/learn-go-language/images/185.png" alt="pic" />
如果沒有錯誤(由e 返回),就可以使用conn 從套接字中讀寫。在包net 中的原始定義是:
// Read reads data from the connection.
Read(b []byte)(n int, err error)
這使得 conn 成為了 io.Reader。
// Write writes data to the connection.
Write(b []byte)(n int, err error)
這同樣使得 conn 成為了 io.Writer,事實上 conn 是 io.ReadWriter。
但是這些都是隱含的低層 c,通常總是應(yīng)該使用更高層次的包。例如 http 包。一個簡單的 http Get 作為例子:
http://wiki.jikexueyuan.com/project/learn-go-language/images/186.png" alt="pic" />
0 .需要的導(dǎo)入;
Q28. (2) 進(jìn)程
Pid 0 has 2 children: [1 2]
Pid 490 has 2 children: [1199 26524]
Pid 1824 has 1 child: [7293]
PID PPID COMMAND
9024 9023 zsh
19560 9024 ps
http://wiki.jikexueyuan.com/project/learn-go-language/images/187.png" alt="pic" />
Q29. (0) 單詞和字母統(tǒng)計
1 .編寫一個從標(biāo)準(zhǔn)輸入中讀取文本的小程序,并進(jìn)行下面的操作:
換句話說,實現(xiàn)一個 wc(1)(參閱本地的手冊頁面),然而只需要從標(biāo)準(zhǔn)輸入讀取。
Q30. (0) Uniq
'a' 'b' 'a' 'a' 'a' 'c' 'd' 'e' 'f' 'g'
它將打印出沒有后續(xù)重復(fù)的項目:
'a' 'b' 'a' 'c' 'd' 'e' 'f'
下面列出的 7.8 是 Perl 實現(xiàn)的算法。
http://wiki.jikexueyuan.com/project/learn-go-language/images/188.png" alt="pic" />
Q31. (2) Quine Quine 是一個打印自己的程序。
Q32. (1) Echo 服務(wù)
Q33. (2) 數(shù)字游戲
1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 25; 50; 75; 100
數(shù)字可以多次被選中;
從 1 : : : 1000 中選擇一個隨機(jī)數(shù)i;