深度解析 Golang 函数的奥秘

发表时间: 2023-07-13 23:13

Golang 中的函数是一组用于执行特定任务的代码块,借助函数可以使代码模块化。一个复杂的功能可以被分解为一块块小块的代码,然后可以由不同的人员在不同的时间编写。

函数定义

Golang 中的函数定义由关键字 func 开始,后面跟上函数名、参数列表和返回值列表。函数定义的基本语法如下:

func functionName(parameterList) (returnParameterList) {      // 函数体  }

具体含义如下:

  • functionName:函数名称,用于标识该函数。
  • parameterList:函数接受的参数列表,参数之间使用逗号分隔。如果没有输入参数,则使用空的括号。
  • returnParameterList:函数返回的参数列表,参数之间使用逗号分隔。如果没有返回参数,不写即可。
  • 函数体:包含实现函数功能的代码块。

以下是一个简单的函数定义示例代码:

func add(a, b int) int {      return a + b  }

函数可以接受零个或多个输入参数。这些参数在函数定义时指定,并在函数调用时传递。简单示例如下:

// 接受一个字符串类型参数func printString(s string) {      fmt.Println(s)  }    // 接受两个整数类型参数func add(a, b int) int {      return a + b  }    // 接受一个浮点数和一个整数类型参数func divide(f float64, i int) float64 {      return f / float64(i)  }

在调用函数时,传给函数的实际参数必须与函数定义的参数数量和类型匹配。例如调用 add 函数的示例代码如下:

result := add(2, 3) // 调用add函数,传入两个整数类型参数2和3  fmt.Println(result) // 输出5

Golang 也支持可变参数,可变参数意味着函数可以接受不定数量参数。这些参数的类型和数量可以在运行时确定。可变参数在函数定义的参数列表中使用省略号(...)来表示。示例代码如下:

package main    import "fmt"    func println(args ...interface{}) {      for _, arg := range args {          fmt.Println(arg)      }  }    func main() {      println("Hello, ", "World!")      println("路多辛的博客", 42, true)  }

println 函数接受一个可变参数 args,在函数体中,循环遍历 args 并打印每个参数的值。然后在 main 函数中调用两次 println 函数,每次传递不同数量的参数。

函数可以返回零个或多个参数,这些参数在函数定义时指定,在函数调用时使用变量接收。简单示例如下:

// 返回一个字符串func greet(name string) string {      return "Hello, " + name + "!"  }    // 返回两个整数func add(a, b int) (int, int) {      return a + b, a - b  }    // 返回一个浮点数和一个整数func multiply(f float64, i int) (float64, int) {      return f * float64(i), i  }

在函数调用时,可以使用变量来接收函数的返回参数。例如:

message := greet("路多辛") // 调用greet函数,接收返回的字符串参数 message  fmt.Println(message)     // 输出 "Hello, 路多辛!"

main 函数

main 函数是一个特殊的函数,是程序的入口。main 函数必须定义在 main 包中,不接受任何参数,也没有返回值,每个程序有且只能有一个 main 函数。简单示例如下:

package main    import "fmt"    func main() {      fmt.Println("路多辛的所思所想!")  }

init 函数

init 函数也是一个特殊的函数,和 main 函数一样也是为 Go 编译器保留的特殊用途函数,不接受任何参数,也没有返回值。但是在一个程序中可以创建多个 init 函数,甚至每个文件中也可以创建多个 init 函数。

init 函数会在包内的任何代码块执行前先执行,init函数执行顺序如下:

如果多个包的中的 init 函数都要执行,首先会先按照包名的字段顺序执行(main 包除外,main 包内的 init 函数会等其它所有包中 init 函数执行后再执行),同一个包内的 init 函数按照所在文件的名字的字典顺序执行,同一个文件中的 init 函数按照创建的顺序执行。

闭包(匿名函数)

关于匿名函数和闭包的讲解可以参考之前的文章《Golang 中的闭包(Closures)详解》。

递归函数

调用自身的函数称为递归函数,相互调用的函数称为相互递归函数。递归函数的典型特征是当递归地调用自己时,必须具有终止条件,防止因为无限递归导致堆栈溢出。简单示例如下:

func fibonacci(num int) int {	if num < 2 {		return num	}	return fibonacci(num-1) + fibonacci(num-2)}

小结

Golang 中的函数除了上面介绍的特点外,还有如下特点:

  • 不支持函数重载
  • 同一个包中函数名不能重复(init 函数除外)
  • 不支持默认参数