介绍
函数是一段代码,一旦定义,就可以重用。函数用于通过将代码分解为可在整个程序中多次使用的小型、可理解的任务来使您的代码更易于理解。
Go 附带了一个强大的标准库,其中包含许多预定义的函数。您可能已经从 fmt 包中熟悉的是:
- fmt.Println() 会将对象打印到标准输出(很可能是您的终端)。
- fmt.Printf() 这将允许您格式化打印输出。
函数名称包括括号,并且可能包括参数。
在本教程中,我们将介绍如何定义您自己的函数以在您的编码项目中使用。
定义函数
让我们从经典的“Hello, World!”开始。程序化成一个函数。
我们将在我们选择的文本编辑器中创建一个新的文本文件,并调用程序 hello.go。然后,我们将定义函数。
函数是使用 func 关键字定义的。然后是您选择的名称和一组括号,其中包含函数将采用的任何参数(它们可以为空)。函数代码行用大括号 {} 括起来。
在这种情况下,我们将定义一个名为 hello() 的函数:
hello.go
func hello() {}
这设置了用于创建函数的初始语句。
从这里开始,我们将添加第二行来提供函数功能的说明。在这种情况下,我们将打印 Hello, World!到控制台:
hello.go
func hello() { fmt.Println("Hello, World!") }
我们的函数现在已经完全定义好了,但是如果我们此时运行程序,什么都不会发生,因为我们没有调用该函数。
因此,在我们的 main() 函数块中,让我们用 hello() 调用该函数:
hello.go
package main import "fmt" func main() { hello() } func hello() { fmt.Println("Hello, World!") }
现在,让我们运行程序:
go run hello.go
您将收到以下输出:
Output
Hello, World!
请注意,我们还引入了一个名为 main() 的函数。 main() 函数是一个特殊函数,它告诉编译器程序应该从这里开始。 对于您希望可执行的任何程序(可以从命令行运行的程序),您将需要一个 main() 函数。 main() 函数必须只出现一次,在 main() 包中,并且不接收和返回任何参数。 这允许在任何 Go 程序中执行程序。 根据以下示例:
main.go
package main import "fmt" func main() { fmt.Println("this is the main section of the program") }
函数可以比我们定义的 hello() 函数更复杂。 我们可以在函数块中使用 for 循环、条件语句等。
例如,以下函数使用条件语句检查 name 变量的输入是否包含元音,然后使用 for 循环遍历 name 字符串中的字母。
names.go
package main import ( "fmt" "strings" ) func main() { names() } func names() { fmt.Println("Enter your name:") var name string fmt.Scanln(&name) // Check whether name has a vowel for _, v := range strings.ToLower(name) { if v == 'a' || v == 'e' || v == 'i' || v == 'o' || v == 'u' { fmt.Println("Your name contains a vowel.") return } } fmt.Println("Your name does not contain a vowel.") }
我们在这里定义的 names() 函数设置了一个带有输入的名称变量,然后在 for 循环中设置了一个条件语句。这显示了如何在函数定义中组织代码。但是,根据我们对程序的意图以及我们希望如何设置代码,我们可能希望将条件语句和 for 循环定义为两个独立的函数。
在程序中定义函数使我们的代码模块化和可重用,这样我们就可以调用相同的函数而无需重写它们。
使用参数
到目前为止,我们已经研究了带有空括号且不带参数的函数,但是我们可以在函数定义中的括号内定义参数。
参数是函数定义中的命名实体,指定函数可以接受的参数。在 Go 中,您必须为每个参数指定数据类型。
让我们创建一个将单词重复指定次数的程序。它将采用一个名为 word 的字符串参数和一个名为 reps 的 int 参数来表示重复单词的次数。
repeat.go
package main import "fmt" func main() { repeat("Sammy", 5) } func repeat(word string, reps int) { for i := 0; i < reps; i++ { fmt.Print(word) } }
我们为 word 参数传递了值 Sammy,为 reps 参数传递了 5。 这些值按照给定的顺序与每个参数相对应。 repeat 函数有一个 for 循环,它将迭代 reps 参数指定的次数。 对于每次迭代,都会打印 word 参数的值。
这是程序的输出:
Output SammySammySammySammySammy
如果你有一组参数都是相同的值,你可以省略每次指定类型。 让我们创建一个小程序,接收参数 x、y 和 z,它们都是 int 值。 我们将创建一个函数,在不同的配置中将参数添加在一起。 这些总和将由函数打印。 然后我们将调用该函数并将数字传递给该函数。
add_numbers.go
package main import "fmt" func main() { addNumbers(1, 2, 3) } func addNumbers(x, y, z int) { a := x + y b := x + z c := y + z fmt.Println(a, b, c) }
当我们为 addNumbers 创建函数签名时,我们不需要每次都指定类型,而只在最后指定。
我们为 x 参数传递了数字 1,为 y 参数传递了 2 in,为 z 参数传递了 3 in。这些值按照给定的顺序与每个参数对应。
该程序正在根据我们传递给参数的值进行以下数学运算:
- a = 1 + 2
- b = 1 + 3
- c = 2 + 3
该函数还打印 a、b 和 c,根据这个数学,我们期望 a 等于 3,b 等于 4,c 等于 5。让我们运行程序:
go run add_numbers.go Output 3 4 5
当我们将 1、2 和 3 作为参数传递给 addNumbers() 函数时,我们会收到预期的输出。
参数是通常在函数定义中定义为变量的参数。当您运行方法时,可以为它们赋值,将参数传递给函数。
返回值
可以将参数值传递给函数,函数也可以产生值。
函数可以使用 return 语句生成一个值,该语句将退出函数并可选地将表达式传递回调用者。还必须指定返回数据类型。
到目前为止,我们在函数中使用了 fmt.Println() 语句而不是 return 语句。让我们创建一个程序,而不是打印将返回一个变量。
在一个名为 double.go 的新文本文件中,我们将创建一个将参数 x 加倍并返回变量 y 的程序。我们发出调用以打印结果变量,该变量是通过运行带有 3 的 double() 函数形成的:
double.go
package main import "fmt" func main() { result := double(3) fmt.Println(result) } func double(x int) int { y := x * 2 return y }
我们可以运行程序并查看输出:
go run double.go
Output
6
整数 6 作为输出返回,这是我们将 3 乘以 2 所期望的结果。
如果函数指定了返回值,则必须在代码中提供返回值。 如果不这样做,您将收到编译错误。
我们可以通过用 return 语句注释掉这一行来证明这一点:
double.go
package main import "fmt" func main() { result := double(3) fmt.Println(result) } func double(x int) int { y := x * 2 // return y }
现在,让我们再次运行程序:
go run double.go
Output
./double.go:13:1: missing return at end of function
此处不使用return语句,程序无法编译。
函数在遇到 return 语句时立即退出,即使它们不在函数末尾:
return_loop.go
package main import "fmt" func main() { loopFive() } func loopFive() { for i := 0; i < 25; i++ { fmt.Print(i) if i == 5 { // Stop function at i == 5 return } } fmt.Println("This line will not execute.") }
这里我们遍历一个 for 循环,并告诉循环运行 25 次迭代。但是,在 for 循环中,我们有一个条件 if 语句来检查 i 的值是否等于 5。如果是,我们发出一个 return 语句。因为我们在 loopFive 函数中,所以函数中任何点的任何返回都将退出该函数。结果,我们永远不会到达这个函数的最后一行来打印语句 这行将不会执行..
在 for 循环中使用 return 语句结束函数,因此循环外的行将不会运行。相反,如果我们使用了 break 语句,那么此时只有循环会退出,并且最后一行 fmt.Println() 会运行。
return 语句退出一个函数,如果在函数签名中指定,它可能会返回一个值。
返回多个值
一个函数可以指定多个返回值。让我们检查 repeat.go 程序并让它返回两个值。第一个将是重复值,如果 reps 参数不是大于 0 的值,则第二个将是错误:
return_loop.go
package main import "fmt" func main() { val, err := repeat("Sammy", -1) if err != nil { fmt.Println(err) return } fmt.Println(val) } func repeat(word string, reps int) (string, error) { if reps <= 0 { return "", fmt.Errorf("invalid value of %d provided for reps. value must be greater than 0.", reps) } var value string for i := 0; i < reps; i++ { value = value + word } return value, nil }
repeat 函数所做的第一件事是检查 reps 参数是否为有效值。任何不大于 0 的值都会导致错误。由于我们传入了 -1 的值,这个代码分支就会执行。请注意,当我们从函数返回时,我们必须提供字符串和错误返回值。因为提供的参数导致错误,我们将为第一个返回值传回一个空白字符串,并为第二个返回值传回错误。
在 main() 函数中,我们可以通过声明两个新变量 value 和 err 来接收两个返回值。因为返回中可能有错误,我们想在继续我们的程序之前检查我们是否收到错误。在这个例子中,我们确实收到了一个错误。我们打印出错误并从 main() 函数中返回以退出程序。
如果没有错误,我们将打印出函数的返回值。
注意:最好只返回两个或三个值。此外,您应该始终将所有错误作为函数的最后一个返回值返回。
运行程序将产生以下输出:
Output
invalid value of -1 provided for reps. value must be greater than 0.
在本节中,我们回顾了如何使用 return 语句从函数返回多个值。
结论
函数是在程序中执行操作的指令代码块,有助于使我们的代码可重用和模块化。
- 登录 发表评论