golang教程之可变函数
可变函数
什么是可变函数?
可变参数函数是一个可以接受可变数量参数的函数。
语法
如果函数的最后一个参数用...
表示,则该函数可以接受最后一个参数的任意数量的类型为T
的参数。
请注意,只允许函数的最后一个参数为可变参数。
示例和理解可变函数如何工作
你有没有想过用于向切片附加值的append
函数如何接受任意数量的参数。 这是因为它具有可变功能。
func append(slice []Type, elems ...Type) []Type
以上是追加功能的定义。 在这个定义中,elems是一个可变参数。 因此append
可以接受可变数量的参数。
让我们创建自己的可变函数。 我们将编写一个简单的程序来查找整数输入列表中是否存在整数。
package main
import (
"fmt"
)
func find(num int, nums ...int) {
fmt.Printf("type of nums is %T\n", nums)
found := false
for i, v := range nums {
if v == num {
fmt.Println(num, "found at index", i, "in", nums)
found = true
}
}
if !found {
fmt.Println(num, "not found in ", nums)
}
fmt.Printf("\n")
}
func main() {
find(89, 89, 90, 95)
find(45, 56, 67, 45, 90, 109)
find(78, 38, 56, 98)
find(87)
}
在上面的程序中,func find(num int,nums ... int)
接受nums参数的可变数量的参数。 在函数find
中,nums的类型等价于[] int
,即整数切片。
可变参数函数的工作方式是将传递的参数的可变数量转换为可变参数类型的新切片。 例如,在上面的程序第22行中,find
函数的可变参数个数是89,90,95
。find
函数需要一个可变 int
参数。 因此,这三个参数将由编译器转换为int [] int {89,90,95}
类型的切片,然后它将被传递给find
函数。
在第10行所示,for
循环在nums
切片上的range
,并且如果它存在于切片中则打印num
的位置。 如果不是,则打印出未找到该号码。
上述程序输出,
type of nums is []int
89 found at index 0 in [89 90 95]
type of nums is []int
45 found at index 2 in [56 67 45 90 109]
type of nums is []int
78 not found in [38 56 98]
type of nums is []int
87 not found in []
在上面的程序第25行中,find
函数调用只有一个参数。我们还没有向variadic nums ... int
参数传递任何参数。 这是完全合法的,在这种情况下,nums
是一个长度和容量为0的切片。
将切片传递给可变函数
让我们将一个切片传递给一个可变函数,并从下面的例子中找出发生了什么。
package main
import (
"fmt"
)
func find(num int, nums ...int) {
fmt.Printf("type of nums is %T\n", nums)
found := false
for i, v := range nums {
if v == num {
fmt.Println(num, "found at index", i, "in", nums)
found = true
}
}
if !found {
fmt.Println(num, "not found in ", nums)
}
fmt.Printf("\n")
}
func main() {
nums := []int{89, 90, 95}
find(89, nums)
}
第23行,我们将一个切片传递给一个需要可变数量参数的函数。
这不行。 上面的程序将失败,出现编译错误main.go:23: cannot use nums (type []int) as type int in argument to find
为什么这不起作用? 嗯,这很直接。 find函数的签名如下所示,
func find(num int, nums ...int)
根据可变函数的定义,nums ...int
意味着它将接受int类型的可变数量的参数。
排队号码 在上面的程序中,nums作为可变参数传递给find
函数。 正如我们已经讨论过的,这些可变参数将被转换为int类型的切片,因为find
需要int型可变参数。 在这种情况下,nums已经是一个int切片,并且尝试使用nums创建new []int
切片,即编译器尝试执行
find(89, []int{nums})
因为nums是[]int
而不是int
,所以会失败。
那么有没有办法将切片传递给可变参数函数? 答案是肯定的。
有一个语法糖可用于将切片传递给可变函数。 您必须使用...
后缀切片。如果这样做,切片将直接传递给函数,而不会创建新切片。
在上面的程序中,如果你用find(89,nums ...)
替换第23行中的find(89,nums)
,程序将编译并输出
type of nums is []int
89 found at index 0 in [89 90 95]
这是完整的程序供您参考。
package main
import (
"fmt"
)
func find(num int, nums ...int) {
fmt.Printf("type of nums is %T\n", nums)
found := false
for i, v := range nums {
if v == num {
fmt.Println(num, "found at index", i, "in", nums)
found = true
}
}
if !found {
fmt.Println(num, "not found in ", nums)
}
fmt.Printf("\n")
}
func main() {
nums := []int{89, 90, 95}
find(89, nums...)
}
常见问题
在变量函数中修改切片时,请确保知道自己在做什么。
让我们看一个简单的例子。
package main
import (
"fmt"
)
func change(s ...string) {
s[0] = "Go"
}
func main() {
welcome := []string{"hello", "world"}
change(welcome...)
fmt.Println(welcome)
}
您认为上述程序的输出是什么? 如果你认为它会 [Go world]
。恭喜! 你已经理解了可变函数和切片。 如果你弄错了,没什么大不了的,让我解释一下我们如何得到这个输出。
在上面的程序第13行中,我们使用语法糖...
并将切片作为变量参数传递给change
函数。
正如我们已经讨论的那样,如果使用了...
,切片本身将作为参数传递,而不会创建新的切片。 因此欢迎将作为参数传递给change
函数。
在change
函数内部,切片的第一个元素更改为Go。 因此该程序输出
[Go world]
这是另一个了解可变函数的程序。
package main
import (
"fmt"
)
func change(s ...string) {
s[0] = "Go"
s = append(s, "playground")
fmt.Println(s)
}
func main() {
welcome := []string{"hello", "world"}
change(welcome...)
fmt.Println(welcome)
}
上一篇: 在PowerPoint播放情况下如何随心所欲使用画笔在屏幕上书写
下一篇: 博弈论基础-ACM