1. 文章
  2. 文章详情

Go语言函数(func)

函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码段,其可以提高应用的模块性和代码的重复利用率。

Go 语言支持普通函数、匿名函数和闭包,从设计上对函数进行了优化和改进,让函数使用起来更加方便。

Go 语言的函数:

  • 函数本身可以作为值进行传递。
  • 支持匿名函数和闭包(closure)。
  • 函数可以满足接口。

Go 语言最少有个 main() 函数。

你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。

函数声明告诉了编译器函数的名称,返回类型,和参数。

Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。

函数定义

Go 语言函数定义格式如下:函数声明包括函数名、形式参数列表、返回值列表(可省略)以及函数体。

func 函数名(形式参数列表)(返回值列表){
    函数体
}
func function_name( [parameter list] ) [return_types] {
   函数体
}

形式参数列表描述了函数的参数名以及参数类型,这些参数作为局部变量,其值由参数调用者提供,返回值列表描述了函数返回值的变量名以及类型,如果函数返回一个无名变量或者没有返回值,返回值列表的括号是可以省略的。如果一个函数声明不包括返回值列表,那么函数体执行完毕后,不会返回任何值。

函数定义解析:

  • func:函数由 func 开始声明
  • function_name:函数名称,函数名和参数列表一起构成了函数签名。
  • parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
  • return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
  • 函数体:函数定义的代码集合。

实例

以下实例为 max() 函数的代码,该函数传入两个整型参数 num1 和 num2,并返回这两个参数的最大值:

/* 函数返回两个数的最大值 */
func max(num1, num2 int) int {
   /* 声明局部变量 */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

函数的返回值

Go语言支持多返回值,多返回值能方便地获得函数执行后的多个返回参数,Go语言经常使用多返回值中的最后一个返回参数返回函数执行中可能发生的错误,示例代码如下:

conn, err := connectToNetwork()

在这段代码中,connectToNetwork 返回两个参数,conn 表示连接对象,err 返回错误信息。

其它编程语言中函数的返回值

  • C/C++ 语言中只支持一个返回值,在需要返回多个数值时,则需要使用结构体返回结果,或者在参数中使用指针变量,然后在函数内部修改外部传入的变量值,实现返回计算结果,C++ 语言中为了安全性,建议在参数返回数据时使用“引用”替代指针。
  • C# 语言也没有多返回值特性,C# 语言后期加入的 ref 和 out 关键字能够通过函数的调用参数获得函数体中修改的数据。
  • lua 语言没有指针,但支持多返回值,在大块数据使用时方便很多。

Go语言既支持安全指针,也支持多返回值,因此在使用函数进行逻辑编写时更为方便。

1) 同一种类型返回值

如果返回值是同一种类型,则用括号将多个返回值类型括起来,用逗号分隔每个返回值的类型。

使用 return 语句返回时,值列表的顺序需要与函数声明的返回值类型一致,示例代码如下:

  1. func typedTwoValues() (int, int) {
  2.     return 1, 2
  3. }
  4. func main() {
  5.     a, b := typedTwoValues()
  6.     fmt.Println(a, b)
  7. }

代码输出结果:

1 2

纯类型的返回值对于代码可读性不是很友好,特别是在同类型的返回值出现时,无法区分每个返回参数的意义。

2) 带有变量名的返回值

Go语言支持对返回值进行命名,这样返回值就和参数一样拥有参数变量名和类型。

命名的返回值变量的默认值为类型的默认值,即数值为 0,字符串为空字符串,布尔为 false、指针为 nil 等。

下面代码中的函数拥有两个整型返回值,函数声明时将返回值命名为 a 和 b,因此可以在函数体中直接对函数返回值进行赋值,在命名的返回值方式的函数体中,在函数结束前需要显式地使用 return 语句进行返回,代码如下:

  1. func namedRetValues() (a, b int) {
  2. a = 1
  3. b = 2
  4. return
  5. }

代码说明如下:

  • 第 1 行,对两个整型返回值进行命名,分别为 a 和 b。
  • 第 3 行和第 4 行,命名返回值的变量与这个函数的布局变量的效果一致,可以对返回值进行赋值和值获取。
  • 第 6 行,当函数使用命名返回值时,可以在 return 中不填写返回值列表,如果填写也是可行的,下面代码的执行效果和上面代码的效果一样。
    1. func namedRetValues() (a, b int) {
    2. a = 1
    3. return a, 2
    4. }

提示

同一种类型返回值和命名返回值两种形式只能二选一,混用时将会发生编译错误,例如下面的代码:

  1. func namedRetValues() (a, b int, int)

编译报错提示:

mixed named and unnamed function parameters

意思是:在函数参数中混合使用了命名和非命名参数。

调用函数

函数在定义后,可以通过调用的方式,让当前代码跳转到被调用的函数中进行执行,调用前的函数局部变量都会被保存起来不会丢失,被调用的函数运行结束后,恢复到调用函数的下一行继续执行代码,之前的局部变量也能继续访问。

函数内的局部变量只能在函数体中使用,函数调用结束后,这些局部变量都会被释放并且失效。

Go语言的函数调用格式如下:

返回值变量列表 = 函数名(参数列表)

下面是对各个部分的说明:

  • 函数名:需要调用的函数名。
  • 参数列表:参数变量以逗号分隔,尾部无须以分号结尾。
  • 返回值变量列表:多个返回值使用逗号分隔。
package main

import "fmt"

func main() {
   /* 定义局部变量 */
   var a int = 100
   var b int = 200
   var ret int

   /* 调用函数并返回最大值 */
   ret = max(a, b)

   fmt.Printf( "最大值是 : %d\n", ret )
}

/* 函数返回两个数的最大值 */
func max(num1, num2 int) int {
   /* 定义局部变量 */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

以上实例在 main() 函数中调用 max()函数,执行结果为:

最大值是 : 200

函数参数

函数如果使用参数,该变量可称为函数的形参。

形参就像定义在函数体内的局部变量。

调用函数,可以通过两种方式来传递参数:

传递类型描述
值传递值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。

函数用法

函数用法描述
函数作为另外一个函数的实参函数定义后可作为另外一个函数的实参数传入
闭包闭包是匿名函数,可在动态编程中使用
方法方法就是一个包含了接受者的函数

发表评论

登录后才能评论

评论列表(0条)