傳遞變長參數
如果函數的最後一個參數是採用 ...type
的形式,那麼這個函數就可以處理一個變長的參數,這個長度可以爲 0,這樣的函數稱爲變參函數。
func myFunc(a, b, arg ...int) {}
這個函數接受一個類似某個類型的 slice 的參數(詳見第 7 章),該參數可以通過第 5.4.4 節中提到的 for 循環結構迭代。
示例函數和調用:
func Greeting(prefix string, who ...string)
Greeting("hello:", "Joe", "Anna", "Eileen")
在 Greeting 函數中,變量 who
的值爲 []string{"Joe", "Anna", "Eileen"}
。
如果參數被存儲在一個 slice 類型的變量 slice
中,則可以通過 slice...
的形式來傳遞參數,調用變參函數。
示例 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
寫一個函數,該函數接受一個變長參數並對每個元素進行換行打印。
一個接受變長參數的函數可以將這個參數作爲其它函數的參數進行傳遞:
func F1(s ...string) {
F2(s...)
F3(s)
}
func F2(s ...string) { }
func F3(s []string) { }
變長參數可以作爲對應類型的 slice 進行二次傳遞。
但是如果變長參數的類型並不是都相同的呢?使用 5 個參數來進行傳遞並不是很明智的選擇,有 2 種方案可以解決這個問題:
-
使用結構(詳見第 10 章):
定義一個結構類型,假設它叫
Options
,用以存儲所有可能的參數:type Options struct { par1 type1, par2 type2, ... }
函數 F1 可以使用正常的參數 a 和 b,以及一個沒有任何初始化的 Options 結構:
F1(a, b, Options {})
。如果需要對選項進行初始化,則可以使用F1(a, b, Options {par1:val1, par2:val2})
。 -
使用空接口:
如果一個變長參數的類型沒有被指定,則可以使用默認的空接口
interface{}
,這樣就可以接受任何類型的參數(詳見第 11.9 節)。該方案不僅可以用於長度未知的參數,還可以用於任何不確定類型的參數。一般而言我們會使用一個 for-range 循環以及 switch 結構對每個參數的類型進行判斷:func typecheck(..,..,values … interface{}) { for _, value := range values { switch v := value.(type) { case int: … case float: … case string: … case bool: … default: … } } }