zl程序教程

您现在的位置是:首页 >  其他

当前栏目

Golang 语言函数的高级使用方式

2023-03-20 14:59:58 时间

01 介绍

在 Golang 语言中,除了 main 和 init 函数之外,其他函数还可以接收一个或多个参数,并且 Golang 函数可以接收可变长度的参数,需要注意的是,当 Golang 函数接收可变长度的参数时,需要将可变长度参数放在所有接收参数的最后,实际上,可变长度参数是一个切片类型的参数。

Golang 语言中的函数还可以接收多个返回值,通常会用于返回 error 错误信息。

Golang 语言的函数是第一公民「first-class」,它允许函数赋值给变量,作为参数传递给其他函数,或从其他函数返回。

本文我们介绍 Golang 语言函数的高级使用方式,关于函数的基本使用方式,我们在之前的文章中已经介绍过,本文不再赘述。

02 匿名函数

所谓匿名函数,顾名思义就是没有定义函数名的函数,通常用于只需短期使用的函数。我们还可以将匿名函数赋值给一个变量,通过变量调用匿名函数。我们通过以下示例代码,演示匿名函数的使用方式。

匿名函数 - 无参数和返回值:

func TestAnonymous(t *testing.T) {
 func () {
  t.Log("Hello World")
 }()
}

匿名函数 - 有参数和返回值:

func TestAnonymous(t *testing.T) {
 func (a, b int) int {
  return a + b
 }(1,2)
}

匿名函数 - 赋值给变量:

func TestAnonymous(t *testing.T) {
 sum := func (a, b int) int {
  return a + b
 }
 t.Log(sum(1, 2))
}

03 闭包

在 Golang 语言中,函数支持匿名函数,闭包就是一种特殊的匿名函数,它可以用于访问函数体外部的变量。

示例代码:

func TestClosures(t *testing.T) {
 x, y := 1, 2
 func (a, b int) {
  t.Log(a + b)
 }(x, y)
}

需要注意的是,在 for ... range ... 中,使用协程执行闭包时,经常会掉「坑」。因为匿名函数可以访问函数体外部的变量,而 for ... range ... 返回的 val 的值是引用的同一个内存地址的数据,所以匿名函数访问的函数体外部的 val 值会是循环中最后输出的一个值。

示例代码:

func TestClosures(t *testing.T) {
 values := []int{1,2,3,4,5}
 for _, val := range values {
  go func() {
   t.Logf("%p %d
", &val, val)
  }()
 }
 time.Sleep(time.Second)
}

避「坑」的方法是使用闭包函数传递参数,示例代码如下:

func TestClosures(t *testing.T) {
 values := []int{1,2,3,4,5}
 for _, val := range values {
  go func(val int) {
   t.Logf("%p %d
", &val, val)
  }(val)
 }
 time.Sleep(time.Second)
}

04 递归

在 Golang 语言中,也支持递归函数。需要注意的是,使用闭包递归,需要在定义闭包之前,显式声明闭包。

示例代码:

func TestRecursion(t *testing.T) {
 var fib func(n int) int
 fib = func (n int) int {
  if n < 2 {
   return n
  }
  return fib(n - 1) + fib(n -2)
 }
 t.Log(fib(7))
}

05 自定义函数类型

在 Golang 语言中,我们也可以像定义结构体类型一样,定义函数类型。

示例代码:

type sum func(int, int) int

自定义的函数类型,可以作为高阶函数的参数或返回值。

06 高阶函数

高阶函数是接收参数或返回值是函数类型的变量的函数,也就是说高阶函数是操作其他函数的函数。

函数作为参数:

func TestHigherOrder(t *testing.T) {
 t.Log(operation(1, 2, func(x, y int) int {
  return x + y
 }))
}

func operation(x, y int, operaFuc func(int, int) int) int {
 rst := operaFuc(x, y)
 return rst
}

函数作为返回值:

func TestHigherOrder(t *testing.T) {
 sum := operation1()
 t.Log(sum(2, 3))
}

func operation1() func(x, y int) int {
 sum := func(x, y int) int {
  return x + y
 }
 return sum
}

07 总结

本文我们介绍了 Golang 语言中函数的高级使用方式,包含匿名函数、闭包、递归、自定义函数类型和高阶函数,并分别列举了一个简单示例,感兴趣的读者朋友,可以在本地运行示例代码,并通过修改调式代码,加深理解。

参考资料: https://gobyexample.com/closures https://gobyexample.com/recursion https://zetcode.com/golang/function/ https://golangbot.com/first-class-functions/ https://www.golangprograms.com/go-language/functions.html https://golangbyexample.com/function-golang-complete-guide/