如果函數(shù)的最后一個參數(shù)是采用 ...type
的形式,那么這個函數(shù)就可以處理一個變長的參數(shù),這個長度可以為 0,這樣的函數(shù)稱為變參函數(shù)。
func myFunc(a, b, arg ...int) {}
這個函數(shù)接受一個類似某個類型的 slice 的參數(shù)(詳見第 7 章),該參數(shù)可以通過第 5.4.4 節(jié)中提到的 for 循環(huán)結構迭代。
示例函數(shù)和調用:
func Greeting(prefix string, who ...string)
Greeting("hello:", "Joe", "Anna", "Eileen")
在 Greeting 函數(shù)中,變量 who
的值為 []string{"Joe", "Anna", "Eileen"}
。
如果參數(shù)被存儲在一個 slice 類型的變量 slice
中,則可以通過 slice...
的形式來傳遞參數(shù),調用變參函數(shù)。
示例 6.7 varnumpar.go
package main
import "fmt"
func main() {
x := min(1, 3, 2, 0)
fmt.Printf("The minimum is: %d\n", x)
slice := []int{7,9,3,5,1}
x = min(slice...)
fmt.Printf("The minimum in the slice is: %d", x)
}
func min(s ...int) int {
if len(s)==0 {
return 0
}
min := s[0]
for _, v := range s {
if v < min {
min = v
}
}
return min
}
輸出:
The minimum is: 0
The minimum in the slice is: 1
練習 6.3 varargs.go
寫一個函數(shù),該函數(shù)接受一個變長參數(shù)并對每個元素進行換行打印。
一個接受變長參數(shù)的函數(shù)可以將這個參數(shù)作為其它函數(shù)的參數(shù)進行傳遞:
func F1(s ...string) {
F2(s...)
F3(s)
}
func F2(s ...string) { }
func F3(s []string) { }
變長參數(shù)可以作為對應類型的 slice 進行二次傳遞。
但是如果變長參數(shù)的類型并不是都相同的呢?使用 5 個參數(shù)來進行傳遞并不是很明智的選擇,有 2 種方案可以解決這個問題:
使用結構(詳見第 10 章):
定義一個結構類型,假設它叫 Options
,用以存儲所有可能的參數(shù):
type Options struct {
par1 type1,
par2 type2,
...
}
函數(shù) F1 可以使用正常的參數(shù) a 和 b,以及一個沒有任何初始化的 Options 結構: F1(a, b, Options {})
。如果需要對選項進行初始化,則可以使用 F1(a, b, Options {par1:val1, par2:val2})
。
使用空接口:
如果一個變長參數(shù)的類型沒有被指定,則可以使用默認的空接口 interface{}
,這樣就可以接受任何類型的參數(shù)(詳見第 11.9 節(jié))。該方案不僅可以用于長度未知的參數(shù),還可以用于任何不確定類型的參數(shù)。一般而言我們會使用一個 for-range 循環(huán)以及 switch 結構對每個參數(shù)的類型進行判斷:
func typecheck(..,..,values … interface{}) {
for _, value := range values {
switch v := value.(type) {
case int: …
case float: …
case string: …
case bool: …
default: …
}
}
}