Go从入门到精通——使用函数
使用函数
本章介绍如下内容
- 函数是什么
- 定义不定参数函数
- 使用具名函数
- 使用递归函数
- 将函数作为值传递
函数是另一个核心要素,不仅仅是 Go 语言,在日常编程中亦是如此。
1.1 函数是什么?
简单地说,函数接受输入并返回输出。数据流经过函数时,将被变换。一个典型的示例是将两个数相加的简单函数,它接受两个数字,将它们相加并返回结果。
func addUp(x int,y int) int{ return x + y }
1.1.1 函数的结构
在 Go 语言中,函数向编译器和程序员提供了有关的信息,这些信息指出了函数将接受什么样的输入并提供什么样的输出。这种信息是在函数的第一行中提供的,而这一行被称为函数签名。我们再以函数 addUp 为例,阐述 Go 语言中函数的结构是什么样的。
func addUp(x int,y int) int{ return x + y }
关键字 func 指出这是一个函数的开头位置。接下来是函数名,这是可选的,但能够让您在其他地方调用(或使用)这个函数。接下来是一对括号,指出了函数接受什么样的值,在这里,是两个类型为 int 的值(带符号的整数,长度至少为 32 位)。在右括号后面是返回值,这里也是一个类型为 int 的值。左括号表示接下来为函数体,函数体以右括号结束。如果函数签名声明了返回值,则函数体必须以终止语句结束。通常有一个返回值,但并非总是如此。
1.1.2 返回单个值
package main import ( "fmt" ) func isEven(i int) bool { return i%2 == 0 } func main() { fmt.Printf("%v\n", isEven(1)) fmt.Printf("%v\n", isEven(2)) }
要调用函数,可通过名称来对其进行引用,并提供所需的参数。调用了函数 isEven 两次,并将结果打印到终端。对函数调用次数没有任何限制。
1.1.3 返回多个值
在 Go 语言中,可在函数签名中声明多个返回值,让函数返回多个结果。在这种情况下,终止语句可返回多个值。在下面的例子中,函数签名指出函数不接受任何参数,并返回一个整数和一个字符串。在函数体中,return 语句返回了多个用逗号分隔的值。
func getPrize() (int, string) { i :=2 s := "goldfish" return i, s }
调用这个函数时,可直接将返回值赋给变量并使用它们。
func main(){ quantity, prize := getPrize() fmt.Printf("You won %v %v\n", quantity, prize) }
程序清单:演示了一个返回多个结果的函数
package main import "fmt" func getPrize() (int, string) { i := 2 s := "goldfish" return i, s } func main() { quantity, prize := getPrize() fmt.Printf("You won %v %v\n", quantity, prize) }
1.2 定义不定参数函数
不定参数函数是参数数量不确定的函数。通俗地说,这意味着它们接受可变数量的参数。在 Go 语言中,能够传递可变数量的参数,但它们的类型必须与函数签名指定的类型相同。要指定不定参数,可使用 3 个点(...)。在下面的示例中,函数签名指定函数可接受任意数量的 int 参数。
func sumNumbers(numbers...int) int{ }
这个函数可接受一个或多个整数,您可使用它来计算任意多个整数的和并返回单个整数。在这个函数中,变量 numbers 是一个包含所有参数的切片。
func sumNumbers(numbers...int) int { total := 0 for _, nmuber :=range numbers { total += numbers } return total }
您可使用这个函数来计算一系列整数的和。
func main(){ result := sumNumbers(1,2,3,4) fmt.Printf("The result is %v\n",result) }
程序清单:使用了一个不定参数函数来将多个整数相加。
package main import "fmt" func sumNumbers(numbers ...int) int { total := 0 for _, number := range numbers { total += number } return total } func main() { result := sumNumbers(1, 2, 3, 4) fmt.Printf("The result is %v\n", result) }
1.3 使用具名返回值
具名返回值让函数能够在返回前将值赋给具名变量,这有助于提升函数的可读性,使其功能更加明确。要使用具名返回值,可在函数签名的返回值部分指定变量名。
func sayHi()(x,y string){}
这个签名指定将返回两个值,它们的类型都为 string;它还指定了变量名(x 和 y),可在函数体中给它们赋值。
func sayHi() (x,y string){ x = "hello" y = "world" return }
这个函数体中,在终止语句 return 前给具名变量进行了赋值。使用具名返回值时,无须显式地返回相应的变量。这被称为裸 return 语句。
func main(){ fmt.Println(sayHi()) }
调用这个函数时,将按声明顺序返回具名变量。
程序清单:具名返回值
package main import "fmt" func sayHi() (x, y string) { x = "hello" y = "World" return } func main() { fmt.Println(sayHi()) }
1.4 使用递归函数
递归函数是不断调用自己直到满足特定条件的函数。要在函数中实现递归,可将调用自己的代码作为终止语句中的返回值。
程序清单:演示一个不断调用自己直到满足特定条件的函数。
package main import "fmt" func feedMe(portion int, eaten int) int { eaten = portion + eaten if eaten >= 5 { fmt.Printf("I'n full! I've eaten %d\n", eaten) return eaten } fmt.Printf("portion:%v,eaten: %v ", portion, eaten) fmt.Printf("I'm still hungry! I've eaten %d\n", eaten) return feedMe(portion, eaten) } func main() { feedMe(1, 0) }
1.5 将函数作为值传递
Go 语言提供了一些函数式的编程功能,如能够将一个函数作为参数传递给其他函数。Go 将函数视为一种类型,因此可将函数赋给变量,以后再通过变量来调用它们。
func main(){ fn := func() { fmt.Println("function called") } }
- 使用简短变量赋值运算符将一个函数赋给了变量 fn。
- 声明这个函数并将其定义为打印一行文本,让您知道它被调用了。
- 在变量名 fn 后使用 () 调用这个函数。
在 Go 语言中,函数是一种类型,因此可将其传递给其他函数。我们对前一个示例进行扩展,将变量 fn 传递给一个函数,并在这个函数中调用它。
程序清单:将函数作为参数传递
package main import "fmt" func anotherFunction(f func() string) string { return f() } func main() { fn := func() string { return "function called" } fmt.Println(anotherFunction(fn)) }
请注意,函数 anotherFunction 的签名中包含一个子函数签名,这表明这个参数是一个返回字符串的函数。接受函数依然需要声明其返回类型,它可以是任何类型,但这里也是字符串。
Go 语言中自定义函数要注意以下几点写法:
- 以关键字 func 开头自定义一个函数。
- 函数的名字与变量命名的要求基本一致。
- 函数后面的圆括号中定义了本函数接受的各个参数及其类型。
- 如果函数有返回值,在函数圆括号后应标明返回值的类型。
- 函数内部的所有代码应包含在一个花括号(大括号)中。
- 如果函数有返回值,必须至少有一条 return 语句来返回结果值,每一个 return 语句都是该函数代码执行的终点,意味着 return 语句返回结果值后将不再往下执行其他代码。
- 如果函数没有返回值,也可以用不带返回值的 return 语句来返回(强制终止函数的运行)。