今天的一个例子中发现,对于在调用可变参数函数时,不是总能使用省略号将一个切片展开,有时候编译器可能会报错,为了清楚的说明这个问题,我用几个小例子一步一步说明。
1、提出假想的需求
假如想要在一堆数据中找出最小的一个,该怎么做?
如果数据的类型为int,那么我可以这么做:
func MinimumInt(first int, others ...int) int {
min := first
for _, value := range others {
if value < min {
min = value
}
}
return min
}
上述的MinimumInt函数的第二个参数声明为:others …int,表示这是一个可变参数,可以给它传入0个或者任意多个int型参数,在该函数内部,它被表示成一个切片。而声明第一个参数,仅仅是为了让调用者必须传入至少一个参数,如果写成
func MinimumInt(others ...int) int {
}
则此函数接收一个可变参数,甚至长度可为0(即不传入参数),显然,不传入参数时调用该函数不满足提出的需求。
对于MinimumInt函数的调用,可通过如下的几种方式:
MinimumInt(10, 15, 32, 46, 2, 3) //1
var sliceInt = []int{
10, 15, 32, 46, 2, 3}
MinimumInt(sliceInt[0], sliceInt[1], sliceInt[2], sliceInt[3], sliceInt[4], sliceInt[5]) //2
MinimumInt(sliceInt[0], sliceInt[1:]...) //3
对于第一种调用方式,直接使用了int类型的字面值常量来作为参数,在MinimumInt函数内部除第一参数外的所有参数被放入到了一个int型切片中进行处理;
第二种调用方式,本质上和第一种相同,只是不再使用字面值常量,而事先构建了一个int型切片,使用该切片的元素依次作为参数;
第三种调用方式,实际上可看做第二种的简化版本,只不过使用了省略号(…)来自动展开切片;
2、完善需求
上面的例子中,我们仅仅做了对int型数据的处理,如果数据是其他类型呢?能否实现一个通用的处理函数,可以处理几乎所有类型的数据?
对于这个问题,在C++中很容易通过泛型来解决,Go中虽不支持这么做,但也还是有解决方法–空接口