mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2024-11-24 15:18:57 +00:00
commit
d0fa50aa12
@ -101,7 +101,7 @@ visitAll := func(items []string) {
|
||||
}
|
||||
```
|
||||
|
||||
在topsort中,首先對prereqs中的key排序,再調用visitAll。因爲prereqs映射的是數組而不是更複雜的map,所以數據的遍歷次序是固定的,這意味着你每次運行topsort得到的輸出都是一樣的。 topsort的輸出結果如下:
|
||||
在topsort中,首先對prereqs中的key排序,再調用visitAll。因爲prereqs映射的是切片而不是更複雜的map,所以數據的遍歷次序是固定的,這意味着你每次運行topsort得到的輸出都是一樣的。 topsort的輸出結果如下:
|
||||
|
||||
```
|
||||
1: intro to programming
|
||||
@ -119,7 +119,7 @@ visitAll := func(items []string) {
|
||||
13: programming languages
|
||||
```
|
||||
|
||||
讓我們迴到findLinks這個例子。我們將代碼移動到了links包下,將函數重命名爲Extract,在第八章我們會再次用到這個函數。新的匿名函數被引入,用於替換原來的visit函數。該匿名函數負責將新連接添加到數組中。在Extract中,使用forEachNode遍歷HTML頁面,由於Extract隻需要在遍歷結點前操作結點,所以forEachNode的post參數被傳入nil。
|
||||
讓我們迴到findLinks這個例子。我們將代碼移動到了links包下,將函數重命名爲Extract,在第八章我們會再次用到這個函數。新的匿名函數被引入,用於替換原來的visit函數。該匿名函數負責將新連接添加到切片中。在Extract中,使用forEachNode遍歷HTML頁面,由於Extract隻需要在遍歷結點前操作結點,所以forEachNode的post參數被傳入nil。
|
||||
|
||||
```Go
|
||||
gopl.io/ch5/links
|
||||
@ -234,7 +234,7 @@ http://research.swtch.com/gotour
|
||||
|
||||
當所有發現的鏈接都已經被訪問或電腦的內存耗盡時,程序運行結束。
|
||||
|
||||
**練習5.10:** 重寫topoSort函數,用map代替數組併移除對key的排序代碼。驗證結果的正確性(結果不唯一)。
|
||||
**練習5.10:** 重寫topoSort函數,用map代替切片併移除對key的排序代碼。驗證結果的正確性(結果不唯一)。
|
||||
|
||||
**練習5.11:** 現在線性代數的老師把微積分設爲了前置課程。完善topSort,使其能檢測有向圖中的環。
|
||||
|
||||
|
@ -1,3 +1,68 @@
|
||||
## 5.7. 可變參數
|
||||
|
||||
TODO
|
||||
參數數量可變的函數稱爲爲可變參數函數。典型的例子就是fmt.Printf和類似函數。Printf首先接收一個的必備參數,之後接收任意個數的後續參數。
|
||||
|
||||
在聲明可變參數函數時,需要在參數列表的最後一個參數類型之前加上省略符號“...”,這表示該函數會接收任意數量的該類型參數。
|
||||
|
||||
```Go
|
||||
gopl.io/ch5/sum
|
||||
func sum(vals...int) int {
|
||||
total := 0
|
||||
for _, val := range vals {
|
||||
total += val
|
||||
}
|
||||
return total
|
||||
}
|
||||
```
|
||||
sum函數返迴任意個int型參數的和。在函數體中,vals被看作是類型爲[] int的切片。sum可以接收任意數量的int型參數:
|
||||
|
||||
```Go
|
||||
fmt.Println(sum()) // "0"
|
||||
fmt.Println(sum(3)) // "3"
|
||||
fmt.Println(sum(1, 2, 3, 4)) // "10"
|
||||
```
|
||||
|
||||
在上面的代碼中,調用者隱式的創建一個數組,併將原始參數複製到數組中,再把數組的一個切片作爲參數傳給被調函數。如果原始參數已經是切片類型,我們該如何傳遞給sum?隻需在最後一個參數後加上省略符。下面的代碼功能與上個例子中最後一條語句相同。
|
||||
|
||||
```Go
|
||||
values := []int{1, 2, 3, 4}
|
||||
fmt.Println(sum(values...)) // "10"
|
||||
```
|
||||
|
||||
雖然在可變參數函數內部,...int 型參數的行爲看起來很像切片類型,但實際上,可變參數函數和以切片作爲參數的函數是不同的。
|
||||
|
||||
```Go
|
||||
func f(...int) {}
|
||||
func g([]int) {}
|
||||
fmt.Printf("%T\n", f) // "func(...int)"
|
||||
fmt.Printf("%T\n", g) // "func([]int)"
|
||||
```
|
||||
|
||||
可變參數函數經常被用於格式化字符串。下面的errorf函數構造了一個以行號開頭的,經過格式化的錯誤信息。函數名的後綴f是一種通用的命名規范,代表該可變參數函數可以接收Printf風格的格式化字符串。
|
||||
|
||||
```Go
|
||||
func errorf(linenum int, format string, args...interface{})
|
||||
{
|
||||
fmt.Fprintf(os.Stderr, "Line %d: ", linenum)
|
||||
fmt.Fprintf(os.Stderr, format, args…)
|
||||
fmt.Fprintln(os.Stderr)
|
||||
}
|
||||
linenum, name := 12, "count"
|
||||
errorf(linenum, "undefined: %s", name) // "Line 12:
|
||||
undefined: count"
|
||||
```
|
||||
|
||||
interfac{}表示函數的最後一個參數可以接收任意類型,我們會在第7章詳細介紹。
|
||||
|
||||
**練習5.15:** 編寫類似sum的可變參數函數max和min。考慮不傳參時,max和min該如何處理,再編寫至少接收1個參數的版本。
|
||||
|
||||
**練習5.16:**編寫多參數版本的strings.Join。
|
||||
|
||||
**練習5.17:**編寫多參數版本的ElementsByTagName,函數接收一個HTML結點樹以及任意數量的標籤名,返迴與這些標籤名匹配的所有元素。下面給出了2個例子:
|
||||
|
||||
```Go
|
||||
func ElementsByTagName(doc *html.Node, name...string)
|
||||
[]*html.Node
|
||||
images := ElementsByTagName(doc, "img")
|
||||
headings := ElementsByTagName(doc, "h1", "h2", "h3", "h4")
|
||||
```
|
Loading…
Reference in New Issue
Block a user