介绍
function 是一个代码的部分,一旦定义,可以重复使用. 函数被用来使您的代码更容易理解,通过将其分解为小、易于理解的任务,可以在整个程序中多次使用。
Go船有强大的标准库,有许多预定义的功能. 那些你可能已经熟悉从 fmt包是:
fmt.Println()
将打印对象以标准化(最有可能是您的终端)。
函数名包括关节,并可能包括参数。
在本教程中,我们将讨论如何在您的编码项目中定义自己的函数。
定义一个函数
让我们先把经典的)变成一个函数。
我们将在我们所选择的文本编辑器中创建一个新的文本文件,并将该程序称为hello.go
。
一个函数是通过使用)的关节组合。
在这种情况下,我们将定义一个名为hello()
的函数:
1[label hello.go]
2func hello() {}
此设置了创建函数的初始语句。
从这里开始,我们将添加第二行以提供该函数所需的指示,在这种情况下,我们将打印Hello, World!
到控制台:
1[label hello.go]
2func hello() {
3 fmt.Println("Hello, World!")
4}
我们的函数现在已经完全定义了,但如果我们在这个时候运行该程序,就不会发生什么,因为我们没有调用该函数。
所以,在我们的)`来调用函数:
1[label hello.go]
2package main
3
4import "fmt"
5
6func main() {
7 hello()
8}
9
10func hello() {
11 fmt.Println("Hello, World!")
12}
现在,让我们运行这个程序:
1go run hello.go
您将收到以下输出:
1[secondary_label Output]
2Hello, World!
通知:我们还引入了一个名为 " main() " 的函数。 ‘main ()' 函数是一个特殊函数,它告诉编译器,程序应该在这里启动 . 对于任何想要被_可执行_的程序(一个可以从命令行运行的程序),您需要)' 函数必须只显示一次,在`main ()' -- -- package -- -- 中,接收和返回任何论据。 这允许任何 Go 程序中的 [程序执行] (https://golang.org/ref/spec# Program_execution] 。 例如:
1[label main.go]
2package main
3
4import "fmt"
5
6func main() {
7 fmt.Println("this is the main section of the program")
8}
我们可以使用(https://andsky.com/tech/tutorials/how-to-construct-for-loops-in-go),(https://andsky.com/tech/tutorials/how-to-write-conditional-statements-in-go),以及更多在我们的函数块内。
例如,下列函数使用条件语句来检查名称
变量的输入是否包含语音,然后使用为
循环重复名称
字符串中的字母。
1[label names.go]
2package main
3
4import (
5 "fmt"
6 "strings"
7)
8
9func main() {
10 names()
11}
12
13func names() {
14 fmt.Println("Enter your name:")
15
16 var name string
17 fmt.Scanln(&name)
18 // Check whether name has a vowel
19 for _, v := range strings.ToLower(name) {
20 if v == 'a' || v == 'e' || v == 'i' || v == 'o' || v == 'u' {
21 fmt.Println("Your name contains a vowel.")
22 return
23 }
24 }
25 fmt.Println("Your name does not contain a vowel.")
26}
我们在这里定义的名称()
函数会设置一个名称
变量与输入,然后在for
循环中设置一个条件陈述. 这表明代码如何在函数定义中进行组织。
在程序中定义函数使我们的代码模块化和可重复使用,以便我们可以调用相同的函数而不重写它们。
工作与参数
到目前为止,我们已经研究了没有参数的空格符串的函数,但我们可以在它们的符串中定义函数定义中的参数。
在 Go 中,您必须为每个参数指定 data type。
让我们创建一个程序,重复一个单词一个特定的次数,它将需要一个名为字
的字符串
参数和一个名为reps
的int
参数来重复这个单词的次数。
1[label repeat.go]
2package main
3
4import "fmt"
5
6func main() {
7 repeat("Sammy", 5)
8}
9
10func repeat(word string, reps int) {
11 for i := 0; i < reps; i++ {
12 fmt.Print(word)
13 }
14}
我们输入了Sammy
值为word
参数和5
为reps
参数,这些值以它们所给出的顺序对应于每个参数。repeat
函数有一个for
循环,它会重复reps
参数所指定的次数。
以下是该计划的结果:
1[secondary_label Output]
2SammySammySammySammySammy
如果你有一套具有相同值的参数,你可以忽略每次指定类型。让我们创建一个小程序,其中包括参数x
,y
和z
,这些参数都是int
值。我们将创建一个函数,在不同的配置中将参数合并在一起。这些参数的总和将由函数打印出来。
1[label add_numbers.go]
2package main
3
4import "fmt"
5
6func main() {
7 addNumbers(1, 2, 3)
8}
9
10func addNumbers(x, y, z int) {
11 a := x + y
12 b := x + z
13 c := y + z
14 fmt.Println(a, b, c)
15}
当我们为addNumbers
创建函数签名时,我们不需要每次指定类型,而只是在最后。
我们输入了1
为x
参数,2
为y
参数,3
为z
参数。
该程序基于我们传递给参数的值来做以下数学:
1a = 1 + 2
2b = 1 + 3
3c = 2 + 3
函数还打印了a
,b
和c
,基于这个数学,我们希望a
等于3
,b
等于4
,c
等于5
。
1go run add_numbers.go
1[secondary_label Output]
23 4 5
当我们将)`函数时,我们会收到预期的输出。
参数是通常在函数定义中定义为变量的参数,在运行方法时可以分配值,将参数传入函数中。
返回值
您可以将参数值传输到函数中,并且函数也可以产生值。
函数可以通过返回
语句生成一个值,该语句将退出函数并可选地将一个表达式传回呼叫器。
到目前为止,我们在我们的函数中使用了fmt.Println()
语句而不是return
语句,让我们创建一个程序,而不是打印,它会返回一个变量。
在一个名为double.go
的新文本文件中,我们将创建一个程序,将参数x
加倍并返回变量y
。
1[label double.go]
2package main
3
4import "fmt"
5
6func main() {
7 result := double(3)
8 fmt.Println(result)
9}
10
11func double(x int) int {
12 y := x * 2
13 return y
14}
我们可以运行程序并查看输出:
1go run double.go
1[secondary_label Output]
26
整数6
作为输出返回,这就是我们将3
乘以2
所期望的。
如果函数指定返回,则必须作为代码的一部分提供返回;如果没有,则会收到编译错误。
我们可以通过评论与返回声明的行来证明这一点:
1[label double.go]
2package main
3
4import "fmt"
5
6func main() {
7 result := double(3)
8 fmt.Println(result)
9}
10
11func double(x int) int {
12 y := x * 2
13 // return y
14}
现在,让我们再次运行程序:
1go run double.go
1[secondary_label Output]
2./double.go:13:1: missing return at end of function
在这里没有使用返回
声明,程序无法编译。
函数在击中一个返回
语句时立即退出,即使它们不在函数的末尾:
1[label return_loop.go]
2package main
3
4import "fmt"
5
6func main() {
7 loopFive()
8}
9
10func loopFive() {
11 for i := 0; i < 25; i++ {
12 fmt.Print(i)
13 if i == 5 {
14 // Stop function at i == 5
15 return
16 }
17 }
18 fmt.Println("This line will not execute.")
19}
在这里,我们通过一个for
循环进行迭代,并告诉循环运行25
迭代。然而,在for
循环中,我们有一个有条件的if
陈述来检查i
的值是否等于5
。如果是,我们发出一个return
陈述。因为我们处于loopFive
函数中,函数中的任何一个点的return
都会离开函数。因此,我们从来没有到达这个函数的最后一行来打印这条线不会执行
。
如果,相反,我们使用了 break
语句,只有循环在那个时候会离开,最后一个 fmt.Println()
行会运行。
返回语句退出一个函数,如果在函数签名中指定,则可以返回一个值。
返回多重值
一个函数可以指定多于一个返回值. 让我们检查repeat.go
程序,让它返回两个值. 第一个值是重复值,第二个值是错误,如果reps
参数不大于0
:
1[label repeat.go]
2package main
3
4import "fmt"
5
6func main() {
7 val, err := repeat("Sammy", -1)
8 if err != nil {
9 fmt.Println(err)
10 return
11 }
12 fmt.Println(val)
13}
14
15func repeat(word string, reps int) (string, error) {
16 if reps <= 0 {
17 return "", fmt.Errorf("invalid value of %d provided for reps. value must be greater than 0.", reps)
18 }
19 var value string
20 for i := 0; i < reps; i++ {
21 value = value + word
22 }
23 return value, nil
24}
重复
函数做的第一件事是检查重复
参数是否是有效的值,任何不大于0
的值都会造成错误,因为我们通过了-1
值,这个代码分支将执行。请注意,当我们从函数返回时,我们必须提供字符串
和错误
返回值。
在main()
函数中,我们可以通过声明两个新的变量值
和err
来获得两个返回值,因为返回中可能有错误,所以我们希望在继续使用我们的程序之前检查是否收到错误。
如果没有错误,我们会打印函数的返回值。
<$>[注] 注: 仅返回两个或三个值被认为是最佳的做法,此外,您应该始终返回所有错误作为函数的最后返回值。
运行该程序将产生以下输出:
1[secondary_label Output]
2invalid value of -1 provided for reps. value must be greater than 0.
在本节中,我们审查了如何使用返回
语句来返回函数中的多个值。
结论
函数是指令的代码块,在程序中执行操作,有助于使我们的代码可重复使用和模块化。
要了解更多有关如何使您的代码更模块化,您可以阅读我们的指南在 如何在Go中写包。