Go语言函数Function

Go函数不支持嵌套、重载和默认参数

但支持以下特性:

  • 无需声明原型、不定长度参数、多返回值、命名返回值参数、匿名函数、闭包

  • 定义函数使用关键字func,且左大括号不能另起一行

  • 函数也可以作为一种类型使用

不定参数

Go语言函数 - 图1

不定参数的传递:

Go语言函数 - 图2

任意类型的不定参数:

如果你希望传任意类型的不定参数,可以指定类型为interface{},下面是Go语言标准库中fmt.Printf()的函数原型:

  1. func Printf(format string, args ...interface{}){
  2. //...

用interface{}传递任意类型数据是Go语言的管理用法。使用interface{}仍然是类型安全的。
Go语言函数 - 图3
Go语言函数 - 图4

defer

defer的执行方式类似其他语言的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个调用
即使函数发生严重错误也会执行
支持匿名函数的调用
Go语言函数 - 图5

  • 常用于资源清理,文件关闭,解锁以及记录时间等操作

  • 通过与匿名函数配合可以在return之后修改函数计算结果

  • 如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址

Go没有异常机制,但有panic/recover模式来处理错误
Panic可以在任何地方引发,但recover只有在defer调用的函数中有效

函数定义

Go语言函数定义格式如下:

  1. func function_name( [parameter list] ) [return_types] {
  2. 函数体
  3. }

函数定义解析:

  • func:函数由func开始声明

  • function_name:函数名称,函数名称和参数列表一起构成了函数签名;

  • parameter list:参数列表,参数就像一个占位符,当函数被调用时,可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是函数也可以不包含参数。

  • return_types:返回类型,函数返回以列值。return_types是该列值的数据类型。有些功能不需要返回值,这种情况下reutrn_types不是必须的;

  • 函数体:函数定义的代码集合

函数调用

当创建函数时,定义了函数需要做什么,通过调用该函数执行指定任务。
调用函数,向函数传递参数,并返回值。

函数返回多个值

Go函数可以返回多个值。

函数参数

函数如果使用参数,该变量可称为函数的形参
形参就像定义在函数体内的局部变量

调用函数,可以通过两种方式来传递参数:
Go语言函数 - 图6

函数用法

Go语言函数 - 图7

函数作为值:

Go 语言可以很灵活的创建函数,并作为值使用。以下实例中我们在定义的函数中初始化一个变量,该函数仅仅是为了使用内置函数 math.sqrt() ,实例为:

  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. )
  6. func main(){
  7. /* 声明函数变量 */
  8. getSquareRoot := func(x float64) float64 {
  9. return math.Sqrt(x)
  10. }
  11. /* 使用函数 */
  12. fmt.Println(getSquareRoot(9))
  13. }

闭包

Go 语言支持匿名函数,可作为闭包。匿名函数是一个”内联”语句或表达式。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。

以下实例中,我们创建了函数 getSequence() ,返回另外一个函数。该函数的目的是在闭包中递增 i 变量,代码如下:

  1. package main
  2. import "fmt"
  3. func getSequence() func() int {
  4. i:=0
  5. return func() int {
  6. i+=1
  7. return i
  8. }
  9. }
  10. func main(){
  11. /* nextNumber 为一个函数,函数 i 为 0 */
  12. nextNumber := getSequence()
  13. /* 调用 nextNumber 函数,i 变量自增 1 并返回 */
  14. fmt.Println(nextNumber())
  15. fmt.Println(nextNumber())
  16. fmt.Println(nextNumber())
  17. /* 创建新的函数 nextNumber1,并查看结果 */
  18. nextNumber1 := getSequence()
  19. fmt.Println(nextNumber1())
  20. fmt.Println(nextNumber1())
  21. }

方法:

Go 语言中同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。语法格式如下:

  1. func (variable_name variable_data_type) function_name() [return_type]{
  2. /* 函数体*/
  3. }

下面定义一个结构体类型和该类型的一个方法:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. /* 定义函数 */
  6. type Circle struct {
  7. radius float64
  8. }
  9. func main() {
  10. var c1 Circle
  11. c1.radius = 10.00
  12. fmt.Println("Area of Circle(c1) = ", c1.getArea())
  13. }
  14. //该 method 属于 Circle 类型对象中的方法
  15. func (c Circle) getArea() float64 {
  16. //c.radius 即为 Circle 类型对象中的属性
  17. return 3.14 * c.radius * c.radius
  18. }

Go语言函数 - 图8