Q1. (0) For-loop
- 建立一個基於 for 的簡單的循環。使其循環 10 次,而且使用 fmt 包打印出計數 器的值。
- 用 goto 改寫 1 的循環。關鍵字 for 不可以使用。
- 再次改寫這個循環,使其遍歷一個 array,並將這個 array 打印到屏幕上。
Q2. (0) FizzBuzz
- 解決這個叫作 Fizz-Buzz[23] 的問題: 編寫一個程序,打印從 1 到 100 的數字。
當是3的倍數就打印 「Fizz」 代替數字,當是5的倍數就打印 「Buzz」。
當數字同時是3和5的倍數 時,打印 「FizzBuzz」。
Q3. (1) 字符串
- 創建一個 Go 程序打印下面的內容(到 100 個字符):
A
AA
AAA
AAAA
AAAAA
AAAAAA
AAAAAAA
…
- 創建一個程序統計字符串裏的字符數量:
asSASA ddd dsjkdsjs dk
同時輸出這個字符串的字節數。
提示: 看看 unicode/utf8 包。
- 擴展/修改上一個問題的程序,替換位置 4 開始的三個字符爲 「abc」。
- 編寫一個 Go 程序能夠逆轉字符串,例如 「foobar」 被打印成 「raboof」。
Q4. (1) 平均值
- 編寫計算一個類型是 float64 的 slice 的平均值的代碼。在稍候的練習 Q5 中 將會改寫爲函數。
Q5. (0) 平均值
- 編寫一個函數用於計算一個 float64 類型的 slice 的平均值。
Q6. (0) 整數順序
- 編寫函數,返回其(兩個)參數正確的(天然)數字順序:
f(7,2) → 2,7
f(2,7) → 2,7
Q7. (1) 做用域
- 下面的程序有什麼錯誤?
package main
import "fmt"
func main() {
for i := 0 ; i < 10 ; i++ {
fmt.Printf("%v\n", i)
}
fmt.Printf("%v\n", i)
}
Q8. (1) 棧
- 建立一個固定大小保存整數的棧。它無須超出限制的增加。定義 push 函數—— 將數據放入棧,和 pop 函數——從棧中取得內容。棧應當是後進先出(LIFO) 的。
- 更進一步。編寫一個 String 方法將棧轉化爲字符串形式的表達。能夠這樣的 方式打印整個棧:
fmt.Printf("My stack %v\n", stack)
棧能夠被輸出成這樣的形式:
[0:m] [1:l] [2:k]
Q9. (1) 變參
- 編寫函數接受整數類型變參,而且每行打印一個數字。
Q10. (1) 斐波那契
- 斐波那契數列以:
1, 1, 2, 3, 5, 8, 13, . . . 開始。
或者用數學形式表達:
x1 = 1; x2 =1; xn = xn−1 + xn−2 ∀n > 2。
編寫一個接受 int 值的函數,並給出這個值獲得的斐波那契數列。
Q11. (1) map 函數
map() 函數是一個接受一個函數和一個列表做爲參數的函數。函數應用於列表中的每一個元素,而一個新的包含有計算結果的列表被返回。所以:
map(f(),(a1, a2, . . . , an−1, an)) = (f(a1), f(a2), . . . , f(an−1), f(an))算法
- 編寫 Go 中的簡單的 map() 函數。它能工做於操做整數的函數就能夠了。
- 擴展代碼使其工做於字符串列表。
Q12. (0) 最小值和最大值
- 編寫一個函數,找到 int slice ([]int) 中的最大值。
- 編寫一個函數,找到 int slice ([]int) 中的最小值。
Q13. (1) 冒泡排序
-
編寫一個針對 int 類型的 slice 冒泡排序的函數。
它在一個列表上重複步驟來排序,比較每一個相䩪的元素,而且順序錯誤的時候,交換它們。
一遍一遍掃描列表,直到沒有交換爲止,這意 味着列表排序完成。
算法得名於更小的元素就像 「泡泡」 同樣冒到列表的別端。小程序
這裏有一個過程代碼做爲示例:
procedure bubbleSort( A : list of sortable items )
do
swapped = false
for each i in 1 to length(A) - 1 inclusive do:
if A[i-1] > A[i] then
swap( A[i-1], A[i] )
swapped = true
end if
end for
while swapped
end procedure併發
Q14. (1) 函數返回一個函數
- 編寫一個函數返回另外一個函數,返回的函數的做用是對一個整數 +2。函數的名稱叫作 plusTwo。而後能夠像下面這樣使用:
p := plusTwo()
fmt.Printf("%v\n", p(2))
應該打印 4
- 使 1 中的函數更加通用化,建立一個 plusX(x) 函數,返回一個函數用於對整 數加上 x。
Q15. (0) stack 包
- 參考 Q8 練習。在這個練習中將從那個代碼中創建一個獨立的包。爲 stack 的實現建立一個合適的包,Push、Pop 和 Stack 類型須要被導出。
- 爲這個包編寫一個單元測試,至少測試 Push 後 Pop 的工做狀況。
Q16. (2) 計算器
- 使用 stack 包建立逆波蘭計算器
Q17. (1) 指針運算
- 在正文的第 54 頁有這樣的文字: …這裏沒有指針運算,所以若是這樣寫:p++,它被解釋爲 (p)++: 首先解析引用而後增長值。 當像這樣增長一個值的時候,什麼類型能夠工做?
- 爲何它不能工做在全部類型上?
Q18. (2) 使用 interface 的 map 函數
- 使用練習 Q11 的答案,利用 interface 使其更加通用。讓它至少能同時工做於int 和 string。
Q19. (1) 指針
- 假設定義了下面的結構:
type Person struct {
name string
age int
}
下面兩行之間的區別是什麼?
var p1 Person p2 := new(Person)
- 下面兩個內存分配的區別是什麼?
func Set(t *T) {
x = t
}
和
func Set(t T) {
x= &t
}
Q20. (1) Linked List
- Make use of the package container/list to create a (doubly) linked list. Push the values 1, 2 and 4 to the list and then print it.
- Create your own linked list implementation. And perform the same actions as in question 1
Q21. (1) Cat
- 編寫一個程序,模仿 Unix 的 cat 程序。對於不知道這個程序的人來講,下面的調用顯示了文件 blah 的內容: % cat blah
- 使其支持 n 開關,用於輸出每行的行號。
- 上面問題中,1 提供的解決方案存在一個 Bug。你能定位並修復它嗎?
Q22. (2) 方法調用
- 假設有下面的程序。要注意的是包 container/vector 曾經是 Go 的一部分,可是 當內建的 append 出現後,就被移除了。然而,對於當前的問題這不重要。這個 包實現了有 push 和 pop 方法的棧結構。
package main
import "container/vector"
func main() {
k1 := vector.IntVector{ }
k2 := &vector.IntVector{ }
k3 := new(vector.IntVector)
k1.Push(2)
k2.Push(3)
k3.Push(4)
}
k1,k2 和 k3 的類型是什麼?
- 當前,這個程序能夠編譯而且運行良好。在不一樣類型的變量上 Push 均可以工做。
Push 的文檔這樣描述:
func (p *IntVector) Push(x int) Push 增長 x 到向量的末尾。
那麼接受者應當是 *IntVector 類型,爲何上面的代碼(Push 語句)能夠正確工做? above (the Push statements) work correct then?
Q23. (1) 接口和編譯
- 在第 72 頁的代碼 5.3 編譯正常——就像文中開始描述的那樣。可是當運行的時候,會獲得運行時錯誤,所以有些東西有錯誤。爲何代碼編譯沒有問題呢?
Q24. (1) 指針和反射
- 在第 「自省和反射」 節,第 76 頁的最後一段中,有這樣的描述:
"右邊的代碼沒有問題,而且設置了成員變量 Name 爲 「Albert Einstein」。"
固然,這僅僅工做於調用 Set() 時傳遞一個指針參數。app
爲何是這樣的狀況?函數
Q25. (2) 接口和 max()
- 在練習 Q12 中建立了工做於一個整形 slice 上的最大函數。如今的問題是建立一個顯示最大數字的程序,同時工做於整數和浮點數。雖然在這裏會至關困難, 不過仍是讓程序儘量的通用吧。
Q26. (1) Channel
- 修改在練習 Q1 中建立的程序,換句話說,主體中調用的函數如今是一個goroutine 而且使用 channel 通信。
不用擔憂 goroutine 是如何中止的。
- 在完成了問題 1 後,仍有一些待解決的問題。其中一個麻煩是 goroutine 在main.main() 結束的時候,沒有進行清理。
更糟的是,因爲 main.main() 和main.shower() 的競爭關係,不是全部數字都被打印了。
本應該打印到 9,可是有時只打印到 8。
添加第二個退出 channel,能夠解決這兩個問題。
試試吧。
Q27. (2) 斐波那契 II
- 這是相似的練習,第一個在第 34 頁的練習 10。完整的問題描述:
斐波那契數列以:
1, 1, 2, 3, 5, 8, 13, . . . 開頭。
或用數學形式:
x1 = 1; x2 = 1; xn = xn−1 + xn−2 ∀n > 2。
編寫一個函數接收 int 值,並給出一樣數量的斐波那契數列。 可是如今有額外條件:必須使用 channel。
Q28. (2) 進程
-
編寫一個程序,列出全部正在運行的進程,並打印每一個進程執行的子進程個數。 輸出應當相似:
Pid 0 has 2 children: [1 2]
Pid 490 has 2 children: [1199 26524]
Pid 1824 has 1 child: [7293]
• 爲了獲取進程列表,須要獲得 ps -e -opid,ppid,comm 的輸出。
輸出類 似:
PID PPID COMMAND
9024 9023 zsh
19560 9024 ps
• 若是父進程有一個子進程, 就打印 child, 若是多於一個, 就打印 children;
• 進程列表要按照數字排序,這樣就以 pid 0 開始,依次展現。
這裏有一個 Perl 版本的程序來幫助上手(或者形成絕對的混亂)。oop
!/usr/bin/perl -l
my (%child, $pid, $parent) ;
my @ps=`ps -e -opid,ppid,comm` ; # Capture the output from `ps`
foreach ([@ps][1..$#ps]) { # Discard the header line
($pid, $parent, undef) = split ; # Split the line,discard 'comm'
push @{$child{$parent} }, $pid ; # Save the child PIDs on a list
}單元測試
# Walk through the sorted PPIDs測試
foreach (sort { $a <=> $b } keys %child) {
print "Pid ", $, " has ", @{$child{$} }+0, " child", @{$child{$} } == 1 ? ": " : "ren: ", "\[@{$child{$} }\]" ;
}ui
Q29. (0) 單詞和字母統計
- 編寫一個從標準輸入中讀取文本的小程序,並進行下面的操做:
- 計算字符數量(包括空格);
- 計算單詞數量;
- 計算行數。 換句話說,實現一個 wc(1)(參閱本地的手冊頁面),然而只須要從標準輸入讀 取。
Q30. (0) Uniq
-
編寫一個 Go 程序模仿 Unix 命令 uniq 的功能。程序應當像下面這樣運行,提供一個下面這樣的列表:
'a' 'b' 'a' 'a' 'a' 'c' 'd' 'e' 'f' 'g'
它將打印出沒有後續重複的項目:
'a' 'b' 'a' 'c' 'd' 'e' 'f'
下面列出的 是 Perl 實現的算法。spa
/# !/usr/bin/perl
my @a = qw/a b a a a c d e f g/ ;
print my $first = shift @a ;
foreach (@a) {
if ($first ne $) { print ; $first = $ ; }
}
附加題:
Q31. (2) Quine Quine 是一個打印本身的程序。
- 用 Go 編寫一個 Quine 程序。
Q32. (1) Echo 服務
- 編寫一個簡單的 echo 服務。使其監聽於本地的 TCP 端口 8053 上。它應當能夠讀取一行(以換行符結尾),將這行原樣返回而後關閉鏈接。
- 讓這個服務能夠併發,這樣每一個請求均可以在獨立的 goroutine 中進行處理。
Q33. (2) 數字遊戲
• 從列表中隨機選擇六個數字:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 50, 75, 100
數字能夠屢次被選中;
• 從 1 . . . 1000 中選擇一個隨機數 i;
• 嘗試用先前的六個數字(或者其中的幾個)配合運算符 +,−,∗ 和 /,計算出 i;
例如,選擇了數字:1,6,7,8,8 和 75。而且 i 爲 977。
能夠用許多方法來實現,其 中一種:
((((1 ∗ 6) ∗ 8) + 75) ∗ 8) − 7 = 977
或者
(8 ∗ (75 + (8 ∗ 6))) − (7/1) = 977
- 實現像這樣的數字遊戲。使其打印像上面那樣格式的結果(也就是說,輸出應 當是帶有括號的中序表達式)
- 計算所有可能解,而且所有顯示出來(或者僅顯示有多少個)。在上面的例子 中,有 544 種方法。
Q34. (1) *Finger 守護進程
-
編寫一個 finger 守護進程,能夠工做於 finger(1) 命令。 來自 Debian 的包描述: Fingerd 是一個基於 RFC 1196 [28] 的簡單的守護進程,它爲許多站點提供了 「finger」 程序的接口。這個程序支持返回一個友好的、面向用戶的系統或用戶當前ⱥ況的詳細報告。 最基本的只須要支持用戶名參數。若是用戶有 .plan 文件,則顯示該文件內容。 所以程序須要可以提供:
• 用戶存在嗎?
• 若是用戶存在,顯示 .plan 文件的內容。
格式編輯挺繁瑣的,後續再回給出參考答案