golang的可變參數(shù)
可變參數(shù)就是一個占位符,你可以將1個或者多個參數(shù)賦值給這個占位符,這樣不管實際參數(shù)的數(shù)量是多少,都能交給可變參數(shù)來處
理,我們看一下可變參數(shù)的聲明:
func Printf(format string, a ...interface{}) (n int, err error) func Println(a ...interface{}) (n int, err error)
可變參數(shù)使用name …Type的形式聲明在函數(shù)的參數(shù)列表中,而且需要是參數(shù)列表的最后一個參數(shù),這點與其他語言類似;
可變參數(shù)在函數(shù)中將轉(zhuǎn)換為對應(yīng)的[]Type類型,所以我們可以像使用slice時一樣來獲取傳給函數(shù)的參數(shù)們;
有一點值得注意,golang的可變參數(shù)不需要強制綁定參數(shù)的出現(xiàn)。
舉個例子,我想在c語言中實現(xiàn)一個求和任意個整數(shù)的函數(shù)sum:
int sum(int num, ...) { // todo }
我們只有先指定至少一個固定的形參(num)才能使用…可變參數(shù),在golang中是不需要這樣做的:
func sum(nums ...int) int { //todo }
這也是golang語法簡潔的其中一個體現(xiàn)。
傳遞參數(shù)給…可變參數(shù)
傳遞參數(shù)給帶有可變參數(shù)的函數(shù)有兩種形式,第一種與通常的參數(shù)傳遞沒有什么區(qū)別,拿上一節(jié)的sum舉個例子:
sum(1, 2, 3) sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
除了參數(shù)的個數(shù)是動態(tài)變化的之外和普通的函數(shù)調(diào)用是一致的。
第二種形式是使用…運算符以變量…的形式進行參數(shù)傳遞,這里的變量必須是與可變參數(shù)類型相同的slice,而不能是其他類型(沒錯,
數(shù)組也不可以),看個例子:
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} sum(numbers...) // 和sum(1, 2, 3, 4, 5, 6, 7, 8, 9. 10)等價
這種形式最常用的地方是在內(nèi)置函數(shù)append里:
result := []int{1, 3} data := []int{5, 7, 9} result = append(result, data...) // result == []int{1, 3, 5, 7, 9}
是不是和python的解包操作很像,沒錯,大部分情況下你可以把…運算符當做是golang的unpack操作,不過有幾點不同還是要注意
的:
第一,只能對slice類型使用…運算符:
arr := [...]int{1, 2, 3, 4, 5} sum(arr...) // 編譯無法通過
你會見到這樣的報錯信息:
cannot use arr (type [5]int) as type []int in argument to sum
這是因為可變參數(shù)實際是個slice,…運算符是個語法糖,它把前面的slice直接復(fù)制給可變參數(shù),而不是先解包成獨立的n個參數(shù)再傳
遞,這也是為什么我只說…運算符看起來像unpack的原因。
第二個需要注意的地方是不能把獨立傳參和…運算符混用,再看個例子:
slice := []int{2, 3, 4, 5} sum(1, slice...) // 無法通過編譯
這次你會見到一個比較長的報錯:
too many arguments in call to sum have (number, []int...) want (...int)
這是和前面所說的原因是一樣的,…運算符將不定參數(shù)直接替換成了slice,這樣就導(dǎo)致前一個獨立給出的參數(shù)不再算入可變參數(shù)的范圍
內(nèi),使得函數(shù)的參數(shù)列表從(…int)變成了(int, …int),最終使得函數(shù)類型不匹配編譯失敗。
正確的做法也很簡單,不要混合使用…運算符給可變參數(shù)傳參即可。
讀了這篇文章,再加上一些簡單的聯(lián)系,我相信你們一定也能掌握golang可變參數(shù)的使用。