[Go 入门] 第三章 使用函数

Go 入门系列参考于互联网资料与 人民邮电出版社 《Go 语言入门经典》 与 《Effective Go》,编写目的在于学习交流,如有侵权,请联系删除

函数是另一个核心要素, 本文内容:

函数是什么

函数接受输入并返回输出。数据流经过时,将会被变换,如下是两个数相加的简单函数,接受两个数字并将相加的结果输出

1
2
3
func addUp(x int, y int) int {
return x + y
}

函数的结构

在 Go 中,函数向编译器和程序员提供了有段的信息,这些函数指出了函数将接受什么样的输入并提供什么样的输出。这些信息在函数的第一行提供,称为函数的签名。以上述的 addUp 为例:

关键字 func 指出这是一个函数的开头位置。接下来是函数名,随后是一对括号,指出了函数该接受什么样的值,在这里是两个 int 类型的值。在右括号后面的是返回值,这里也是一个类型为 int 的值。大括号{}包起来的为函数体,如果函数签名声明了返回值,那么函数体必须以终止语句结束,通常有一个返回值,但并非总是如此

返回单个值

假设我们需要编写一个函数来判断输入的数字是否为偶数,那么可有以下假设:

  • 这个函数接受一个整型参数
  • 这个函数返回一个布尔值,如果输入的整数是偶数,则为 true 反之 false
1
2
3
func isEven(i int) bool {
return i%2 == 0
}

返回多个值

在 Go 语言中,可在函数签名中声明多个返回值,让函数返回多个结果,如

1
2
3
4
5
6
7
8
9
10
func getPrize() (int, string) {
i := 2
s := "good"
return i, s
}

func main() {
quantity, prize := getPrize()
fmt.Printf("%v %v\n", quantity, prize)
}

定义不定参数函数

不定参数函数是参数数量不确定的函数。也就说它们可以接受可变数量的参数,它们的类型必须与函数签名指定的类型相同,要指定不定函数,可以使用3个点(…),如下列函数,可以计算输入输入数字参数的和

1
2
3
4
5
6
7
func sumNumbers(numbers...int) int {
total := 0
for _, number := range numbers {
total += number
}
return total
}

使用具名返回值

具名返回值让函数能够在返回前将值赋给具名变量,这有助于提升函数的可读性,使其功能更加明确

1
2
3
4
5
6
7
8
9
func sayHi() (x, y string) {
x = "hello"
y = "world"
return
}

func main() {
fmt.Println(sayHi())
}

在终止语句 return 前给具名变量进行了赋值。使用具名返回值时,无需显式地返回相应的变量,这被称为 裸(naked) return 语句,上述的函数返回值为 hello world

使用递归函数

递归函数是不断调用自己知道满足特定的条件的函数。要在函数中实现递归,可将调用自己的代码作为终止语句中的返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
feedMe(1, 0)
}

func feedMe(portion int, eaten int) int {
eaten = portion + eaten
if eaten >= 5{
fmt.Printf("full, eaten %d \n", eaten)
return eaten
}
fmt.Printf("hungry, eaten %d \n", eaten)
return feedMe(portion, eaten)
}

最后一行的返回值 return feedMe(portion, eaten) 没有返回值,而是在调用自己,这样将再次执行这个函数,只要满足条件 (eaten >= 5) 为止

将函数作为值传递

从本质上说, Go 将函数视为一种类型,因此可将函数赋给变量

1
2
3
4
5
6
7
8
9
10
func anotherFunction(f func() string) string {
return f()
}

func main() {
fn := func() string {
return "function called"
}
fmt.Println(anotherFunction(fn))
}

请注意,函数 anotherFunction 的签名中包含一个子函数签名,这表明这个参数是一个返回字符串的函数,接受函数依然需要声明其返回类型

问题列表

  • 声明函数后,可以修改其参数的数量和类型吗?

    不能。函数声明后,编译器就记录了其签名,并根据签名检查调用该函数时指定的参数数量和类型是否正确

  • 该使用具名返回值吗

    在简短的函数中,可使用具名返回值,但这样可能导致代码阅读起来更困难;在有些情况下,还更容易引入bug,因此当有助于改善可维护性和可读性时才如此

  • 为何应让函数较短

    简短函数有多个优点。它们更易于理解和测试,单个庞大的函数可能导致代码成为联系紧密的整体,进而难以修改


All articles in this blog adopt the CC BY-SA 4.0 agreement unless otherwise stated. Please indicate the source for reprinting!