团队翻译了一篇有关Go中可变参数功能的文章。它的作者解释了可变参数功能与普通功能的不同之处以及如何创建它们。
什么是可变函数
函数是旨在执行特定任务的一段代码。该函数将传递一个或多个参数,并返回一个或多个结果。
变体函数与常规函数相同,但它们可以采用无限数量或可变数量的参数。
func f(elem ...Type)
这是典型的可变参数函数语法。该运算符
...
(也称为装箱运算符)告诉Go将所有类型参数存储Type
在parameter中elem
。换句话说,Go创建一个elem
类型[]Type
为,即切片的变量。并且所有传递给函数的参数都存储在slice中elem
。
让我们看一个函数的例子
append()
。
append([]Type, args, arg2, argsN)
该函数
append
期望第一个参数是一个切片,Type
然后是任意数量的参数。但是,如何在切片中添加s2
切片s1
?
从函数的定义
append()
可以看出,我们无法将两个切片传递给它-Type
只有一个类型实参。因此,我们使用拆箱运算符...
将切片分解为一系列参数。然后可以将它们传递给函数append
。
append(s1, s2...)
...
表示包装操作员和拆包操作员。拆箱运算符始终出现在变量名称之后。
在我们的示例中,切片
s1
和s2
相同类型。我们通常知道函数的参数及其所使用的参数数量。函数accept
如何知道已经传递了多少参数?
如果查看函数声明
append
,则可以看到表达式elems ...Type
。它将所有参数(从第二个参数开始)打包到slice中elems
。
func append(slice []Type, elems ...Type) []Type
仅函数声明中的最后一个参数可以是可变参数。
因此,该函数的第一个参数
append
只是一个切片,因为它被定义为切片。所有后续参数都打包到一个名为的参数中elems
。
现在让我们看看如何创建自己的可变参数函数。
如何创建可变函数
如上所述,可变参数函数是一个接受可变数量参数的常规函数。为此,您需要使用装箱运算符
...Type
。
让我们编写一个
getMultiples
具有第一个factor
类型实参int
(乘数因子)和可变数量的其他类型实参的函数int
。他们将被包装成薄片args
。
用于
make
创建一个空切片,其大小与slice相同args
。使用循环for range
,将切片元素args
乘以factor
。我们将结果放入一个新的空片中multiples
,该空片将作为函数的结果返回。
func getMultiples(factor int, args ...int) []int {
multiples := make([]int, len(args))
for index, val := range args {
multiples[index] = val * factor
}
return multiples
}
这是一个非常简单的函数,将其应用在block中
main()
。
func main() {
s := []int{10, 20, 30}
mult1 := getMultiples(2, s...)
mult2 := getMultiples(3, 1, 2, 3, 4)
fmt.Println(mult1)
fmt.Println(mult2)
}
https://play.go.org/p/BgU6H9orhrn
在上面的示例中,如果您将slice s
getMultiples
作为第二个参数传递给函数,会发生什么情况?编译器将报告一个错误:在参数中,getMultiples
它不能用作s (type [] int)
typeint
。这是因为切片的类型[]int, getMultiples
需要使用来自的参数int
。
切片如何传递给可变参数函数
切片是对数组的引用。那么,当您使用拆箱运算符将切片传递给可变参数函数时会发生什么? Go是创建新切片
args
还是使用旧切片s
?
由于没有比较工具
args == s
,因此需要更改切片args
。然后我们找出原始切片是否已更改s
。
https://play.go.org/p/fbNgVGu6JZO
在上面的示例中,我们稍微更改了功能
getMultiples
。而不是创建一个新的切片,我们将计算结果分配给切片的元素args
,将输入的元素替换为相乘的元素。
结果,我们看到原始切片的值
s
已经变化。如果您通过取消装箱运算符将参数传递给可变参数函数,则Go会使用对原始数据基础的数据数组的引用来创建新切片。请注意不要出错,否则原始数据将因计算而改变。
祝好运!
还有什么要读的: