Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a5ef0b2

Browse files
RickyWang1020Tinywan
authored andcommitted
Update golang_tutorial_12.md
1 parent 7fb7128 commit a5ef0b2

File tree

1 file changed

+85
-14
lines changed

1 file changed

+85
-14
lines changed

‎docs/golang_tutorial_12.md‎

Lines changed: 85 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,50 @@
22
========================
33

44
上一节:[第十一篇 数组和切片](/docs/golang_tutorial_11.md)
5-
下一节:[第十三篇 ](/docs/golang_tutorial_13.md)
5+
下一节:[第十三篇 Map](/docs/golang_tutorial_13.md)
66

77
这是本Golang系列教程的第12篇。
88

99
## 什么是变参函数?
1010

11-
变参函数是指可以接受可变数量的参数的函数
11+
变参函数是指可以接收可变数量的参数的函数
1212

13-
## 语法?
13+
如果一个函数的最后一个参数由 `...T` 表示,则表示该函数可以接收任意数量的类型为 T 的参数。
1414

15-
如果一个函数的最后一个参数由 `...T` 表示,则表示该函数可以接受任意数量的类型为 T 的参数
15+
请注意只有函数的最后一个参数才能指定为可变参数
1616

17-
请注意只有函数的最后一个参数才能指定为可变参数。
17+
## 语法
18+
19+
```golang
20+
func hello(a int, b ...int){
21+
}
22+
```
23+
24+
上述函数中,`b` 就是一个可变参数,因为它的类型定义有 `...` 前缀,因而可以接收任意数量的输入。以下语句可以用来调用这个变参函数:
25+
26+
```golang
27+
hello(1, 2) //passing one argument "2" to b
28+
hello(5, 6, 7, 8, 9) //passing arguments "6, 7, 8 and 9" to b
29+
```
30+
31+
第一行中,我们将 `2` 赋给了 `b` ;第二行中,我们将四个参数 `6, 7, 8, 9` 赋给了 `b`
32+
33+
我们也可以选择不将参数传入变参函数(即:传入"零"个参数),例如:
34+
35+
```golang
36+
hello(1)
37+
```
38+
39+
我们调用了 `hello` 函数,但是没有为 `b` 传入任何参数,这也是完全可以的。
40+
41+
为什么变参函数中的可变参数必须在定义参数时放在最后?作为反例,我们来尝试将 `hello` 函数的第一个参数变成可变参数:
42+
43+
```golang
44+
func hello(b ...int, a int){
45+
}
46+
```
47+
48+
以上函数中,我们将无法为 `a` 传入参数, 因为无论我们在函数中传入多少参数,这些参数都会被赋给可变参数 `b`。上述函数会出现编译错误:`syntax error: cannot use ... with non-final parameter b`,因此可变参数必须在定义参数时被放在最后。
1849

1950
## 案例
2051

@@ -51,7 +82,9 @@ func main() {
5182
}
5283
```
5384

54-
上面的程序中,`func find(num int, nums ...int) `可以接受任意数量的参数。`...int `在内部表示为切片。在这里 `nums` 的类型为 `[]int`
85+
上面的程序中,`func find(num int, nums ...int)` 可以为 `nums` 接收任意数量的参数。在函数内部,`nums` 的类型为 `[]int`,即整数切片类型。
86+
87+
**变参函数会将可变数量的参数转换成相应类型的切片,例如上述函数的第22行,传入 `find` 函数的可变参数是 89,90,95,随后这些参数会被编译器转换为整数切片 `[]int{89, 90, 95}` 然后被送入 `find` 函数内。**
5588

5689
第 10 行利用 `range for` 遍历 `nums` 切片,如果找到 num 则打印 num 所在位置,否则打印没有找到。
5790

@@ -71,11 +104,52 @@ type of nums is []int
71104
87 not found in []
72105
```
73106

74-
在第 25 行,`find `只有一个参数。我们没有传递任何参数给 `nums ...int`。这是合法的,(译者注:如果没有给可变参数传递任何值,则可变参数为 `nil `切片),在这里 `nums `是一个 `nil `切片,长度和容量都是`0`
107+
在第 25 行,`find `只有一个参数。我们没有传递任何参数给 `nums ...int`。这是合法的,(译者注:如果没有给可变参数传递任何值,则可变参数为 `nil` 切片),在这里 `nums` 是一个 `nil` 切片,长度和容量都是`0`
108+
109+
## 切片 VS 可变参数
110+
111+
我们现在肯定会想到一个问题:既然传入的可变参数被转换成了切片,那么我们为何不直接将一个切片传入函数中呢?我们将之前的函数用切片参数来改写:
112+
113+
```golang
114+
package main
115+
116+
import (
117+
"fmt"
118+
)
119+
120+
func find(num int, nums []int) {
121+
fmt.Printf("type of nums is %T\n", nums)
122+
found := false
123+
for i, v := range nums {
124+
if v == num {
125+
fmt.Println(num, "found at index", i, "in", nums)
126+
found = true
127+
}
128+
}
129+
if !found {
130+
fmt.Println(num, "not found in ", nums)
131+
}
132+
fmt.Printf("\n")
133+
}
134+
func main() {
135+
find(89, []int{89, 90, 95})
136+
find(45, []int{56, 67, 45, 90, 109})
137+
find(78, []int{38, 56, 98})
138+
find(87, []int{})
139+
}
140+
```
141+
142+
用可变参数代替切片的优势如下:
143+
144+
1. 不用在每次调用函数时都创建一个新的切片。上述函数中,我们在第22、23、24、25行都创建了新的切片,如果使用变参函数,这些额外的切片创建就可以省略。
75145

76-
## 传递切片给可变参数
146+
2. 在第25行,为了满足 `find` 函数的参数定义,我们创建了一个空的切片,在变参函数中,我们只需要写 `find(87)` 即可。
77147

78-
我们已经提到 `...T `在内部表示为类型是 `[]T` 切片。如果真是这样,可以传递一个切片给可变参数吗?让我们从下面的例子中寻找答案:
148+
3. 我(原文作者)认为带变参函数的程序比带切片的函数可读性强 :)
149+
150+
## 将切片传入可变参数
151+
152+
我们已经提到 `...T` 在内部表示为类型是 `[]T` 切片。如果真是这样,可以传递一个切片给可变参数吗?让我们从下面的例子中寻找答案:
79153

80154
```golang
81155
package main
@@ -104,9 +178,9 @@ func main() {
104178
}
105179
```
106180

107-
在第 23 行,我们没有将若干数量的参数传递给 `find` 的最后一个参数, 而是传递了一个切片。这是非法的,我们不能传递一个切片给可变参数。上面的程序将报错:`main.go:23: cannot use nums (type []int) as type int in argument to find`
181+
在第 23 行,我们没有将若干数量的参数传递给 `find` 函数的最后一个参数, 而是传递了一个切片。这是非法的,我们不能传递一个切片给可变参数。上面的程序将报错:`main.go:23: cannot use nums (type []int) as type int in argument to find`
108182

109-
这里有一个语法糖可以用来将切片传递给变参函数。可以在切片后面加 `...`,这样会将切片展开为其中的各个元素并将它们传递给变参函数。这样该程序将正常工作。
183+
**有一个语法糖可以用来将切片传递给变参函数:在切片后面加 `...`,这样会将切片展开为其中的各个元素并将它们传递给变参函数,程序将正常工作。**
110184

111185
上面的程序如果将第23行的 `find(89, nums)` 改为` find(89, nums...)`,程序将通过编译,并输出如下:
112186

@@ -116,6 +190,3 @@ type of nums is []int
116190
```
117191

118192
变参函数的介绍到此结束。感谢阅读。
119-
120-
上一节:[第十一篇 数组和切片](/docs/golang_tutorial_10.md)
121-
下一节:[第十三篇 Map](/docs/golang_tutorial_12.md)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /