golang:函数

刺骨的言语ヽ痛彻心扉 2021-12-15 14:57 457阅读 0赞

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

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

Go 语言的函数属于“一等公民”(first-class),也就是说:

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

函数声明(函数定义)

函数构成了代码执行的逻辑结构,golang,函数的基本组成为:关键字 func、函数名、参数列表、返回值、函数体和返回语句,每一个程序都包含很多的函数,函数是基本的代码块。

  • 因为golang是编译型语言,所以函数编写的顺序是无关紧要的,鉴于可读性的需求,最好把 main() 函数写在文件的前面,其他函数按照一定逻辑顺序进行编写
  • 编写多个函数的主要目的是将一个需要很多行代码的复杂问题分解为一系列简单的任务来解决,而且,同一个任务(函数)可以被多次调用,有助于代码重用
  • 当函数执行到代码块最后一行}之前或者 return 语句的时候会退出,其中 return 语句可以带有零个或多个参数,这些参数将作为返回值供调用者使用,简单的 return 语句也可以用来结束 for 的死循环,或者结束一个协程(goroutine)

Go语言里面拥三种类型的函数:

  • 普通的带有名字的函数
  • 匿名函数或者 lambda 函数
  • 方法

普通函数声明(定义)

函数声明包括函数名、形式参数列表、返回值列表(可省略)以及函数体。

  1. func 函数名(形式参数列表)(返回值列表){
  2. 函数体
  3. }
  • 形式参数列表描述了函数的参数名以及参数类型,这些参数作为局部变量,其值由参数调用者提供
  • 返回值列表描述了函数返回值的变量名以及类型,如果函数返回一个无名变量或者没有返回值,返回值列表的括号是可以省略的。

如果一个函数声明不包括返回值列表,那么函数体执行完毕后,不会返回任何值,在下面的 hypot 函数中:

  1. func hypot(x, y float64) float64 {
  2. return math.Sqrt(x*x + y*y)
  3. }
  4. fmt.Println(hypot(3,4)) // "5"

x 和 y 是形参名,3 和 4 是调用时的传入的实数,函数返回了一个 float64 类型的值,返回值也可以像形式参数一样被命名,在这种情况下,每个返回值被声明成一个局部变量,并根据该返回值的类型,将其初始化为 0。

如果一个函数在声明时,包含返回值列表,那么该函数必须以 return 语句结尾,除非函数明显无法运行到结尾处,例如函数在结尾时调用了 panic 异常或函数中存在无限循环

正如 hypot 函数一样,如果一组形参或返回值有相同的类型,我们不必为每个形参都写出参数类型,下面 2 个声明是等价的:

  1. func f(i, j, k int, s, t string) {
  2. /* ... */ }
  3. func f(i int, j int, k int, s string, t string) {
  4. /* ... */ }

下面,我们给出 4 种方法声明拥有 2 个 int 型参数和 1 个 int 型返回值的函数,空白标识符_可以强调某个参数未被使用。

  1. func add(x int, y int) int {
  2. return x + y}
  3. func sub(x, y int) (z int) {
  4. z = x - y; return}
  5. func first(x int, _ int) int {
  6. return x }
  7. func zero(int, int) int {
  8. return 0 }
  9. fmt.Printf("%T\n", add) // "func(int, int) int"
  10. fmt.Printf("%T\n", sub) // "func(int, int) int"
  11. fmt.Printf("%T\n", first) // "func(int, int) int"
  12. fmt.Printf("%T\n", zero) // "func(int, int) int"
  • 函数的类型被称为函数的标识符,如果两个函数形式参数列表和返回值列表中的变量类型一一对应,那么这两个函数被认为有相同的类型和标识符,形参和返回值的变量名不影响函数标识符也不影响它们是否可以以省略参数类型的形式表示。
  • 每一次函数在调用时都必须按照声明顺序为所有参数提供实参(参数值),在函数调用时,Go语言没有默认参数值,也没有任何方法可以通过参数名指定形参,因此形参和返回值的变量名对于函数调用者而言没有意义。

在函数中,实参通过值传递的方式进行传递,因此函数的形参是实参的拷贝,对形参进行修改不会影响实参,但是,如果实参包括引用类型,如指针、slice(切片)、map、function、channel 等类型,实参可能会由于函数的间接引用被修改

函数的返回值

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

  1. conn, err := connectToNetwork()

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

同一类型的返回值

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

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

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

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

带有变量名的返回值

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

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

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

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

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

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

编译报错提示:

  1. mixed named and unnamed function parameters

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

调用函数

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

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

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

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

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

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

比如:

  1. result := add(1,1)

发表评论

表情:
评论列表 (有 0 条评论,457人围观)

还没有评论,来说两句吧...

相关阅读

    相关 golang:构造函数

    Go语言的类型或结构体没有构造函数的功能,但是我们可以使用结构体初始化的过程来模拟实现构造函数。 其他编程语言构造函数的一些常见功能及特性如下: 每个类可以添加构造函

    相关 golang 函数 05

     func进行函数声明 函数的左花括号也不能另起一行 不允许函数内嵌定义 支持多返回值、支持命名返回值 函数只能判断是否为nil 参数视为局

    相关 golang中init函数

    init函数有一下几点特性: init函数在main执行之前,自动被调用执行的,不能显示调用 每个包的init函数在包被引用时,自动被调用 每个包可以有多个

    相关 golang:匿名函数

    匿名函数——没有函数名字的函数 Go语言支持匿名函数,即在需要使用函数时再定义函数,匿名函数没有函数名只有函数体,函数可以作为一种类型被赋值给函数类型的变量

    相关 golang函数

    函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码段,其可以提高应用的模块性和代码的重复利用率。 Go 语言支持普通函数、匿名函数和闭包,从设计上对函数进行了优化和