當函數最後一個參數為 *...T* 時(*T* 前面的三個點是特意的),就叫*可變參函數*:```gopackage mainimport "fmt"func sum(numbers ...float64) (res float64) { for _, number := range numbers { res += number } return}func main() { fmt.Println(sum(1.1, 2.2, 3.3))}```可變參函數允許傳遞任意數量(可變)的實參,在函數內部通過一個 [slice](https://golang.org/ref/spec#Slice_types) 來訪問這些參數的值(例如上面代碼中的參數成員)。> 只有在最後一個形參前加上 ...(三個點),才表示這是一個可變參函數。## 實參 vs. 形參在大多數情況下這兩個術語是可以互相通用的,但是實參一般表示涉及在調用函數 / 方法時傳入的參數,形參是特指在函數定義時的參數。```gopackage mainimport "fmt"func sum(a, b float64) (res float64) { return a + b}func main() { fmt.Println(sum(1.1, 1.2))}```- a 和 b 是形參- res 是指定名稱的返回參數- 1.1 和 1.2 是實參## ... 轉換為 slice在可變參函數內部中,...T 類型實際上是一個 []T:```gopackage mainimport "fmt"func f(names ...string) { fmt.Printf("value: %#v\n", names) fmt.Printf("length: %d\n", len(names)) fmt.Printf("capacity: %d\n", cap(names)) fmt.Printf("type: %T\n", names)}func main() { f("one", "two", "three")}```編譯運行代碼後輸出:```> go install github.com/mlowicki/lab && ./bin/labvalue: []string{"one", "two", "three"}type: []stringlength: 3capacity: 3```## 類型的一致性可變參函數並不等同於最後一個形參為傳入 slice 的函數:```gof := func(...int) {}f = func([]int) {}```上面的代碼在編譯期時會報錯:```src/github.com/mlowicki/lab/lab.go:17: cannot use func literal (type func([]int)) as type func(...int) in assignment```## 把三個點放到另一側下面的程式碼片段無法被成功編譯:```gopackage mainimport "fmt"func f(numbers ...int) { fmt.Println(numbers)}func main() { numbers := []int{1, 2, 3} f(numbers)}``````> go install github.com/mlowicki/lab && ./bin/lab# github.com/mlowicki/labsrc/github.com/mlowicki/lab/lab.go:11: cannot use numbers (type []int) as type int in argument to f```這是因為傳遞單個實參的時候必須是 int 類型的,所以很明顯傳遞一個 slice 類型是不被允許的。在 Golang 中有個技巧可以快速解決這個問題:```gopackage mainimport "fmt"func f(numbers ...int) { fmt.Println(numbers)}func main() { numbers := []int{1, 2, 3} f(numbers...)}```在調用函數 *f* 時,三個點(...)放到了實參的**後面**,這是個容易被忽視的改動,但它將 *numbers* 作為形參列表進行傳遞。這個方式實現了用 slice 作為參數去調用可變參函數。可變參數函數實際上是一種文法糖,它只是將 slice 作為最後一個參數而已。可變參函數可以為 APIs 提供更豐富的表現形式,同時也讓開發人員不用再建立臨時 slice。
via: https://medium.com/golangspec/variadic-functions-in-go-13c33182b851
作者:Michał Łowicki 譯者:nicedevcn 校對:polaris1119
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽
271 次點擊