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

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

01

介绍

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

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

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

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

匿名函数

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

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

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\n", &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\n", &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 语言中函数的高级使用方式,包含匿名函数、闭包、递归、自定义函数类型和高阶函数,并分别列举了一个简单示例,感兴趣的读者朋友,可以在本地运行示例代码,并通过修改调式代码,加深理解。

推荐阅读:

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/ 


目录
相关文章
|
2月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
114 4
Golang语言之管道channel快速入门篇
|
2月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
67 4
Golang语言文件操作快速入门篇
|
2月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
104 3
Golang语言之gRPC程序设计示例
|
2月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
86 4
|
2月前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
52 4
Golang语言goroutine协程篇
|
2月前
|
Prometheus Cloud Native Go
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
55 3
Golang语言之Prometheus的日志模块使用案例
|
1月前
|
前端开发 中间件 Go
实践Golang语言N层应用架构
【10月更文挑战第2天】本文介绍了如何在Go语言中使用Gin框架实现N层体系结构,借鉴了J2EE平台的多层分布式应用程序模型。文章首先概述了N层体系结构的基本概念,接着详细列出了Go语言中对应的构件名称,包括前端框架(如Vue.js、React)、Gin的处理函数和中间件、依赖注入和配置管理、会话管理和ORM库(如gorm或ent)。最后,提供了具体的代码示例,展示了如何实现HTTP请求处理、会话管理和数据库操作。
31 0
|
2月前
|
JSON Go 数据格式
Golang语言结构体链式编程与JSON序列化
这篇文章是关于Go语言中结构体链式编程与JSON序列化的教程,详细介绍了JSON格式的基本概念、结构体的序列化与反序列化、结构体标签的使用以及如何实现链式编程。
39 4
|
2月前
|
Go
Golang语言结构体(struct)面向对象编程进阶篇(封装,继承和多态)
这篇文章是关于Go语言中结构体(struct)面向对象编程进阶篇的教程,涵盖了Go语言如何实现封装、继承和多态,以及结构体内存布局的相关概念和案例。
148 4
|
2月前
|
Go
Golang语言基础之接口(interface)及类型断言
这篇文章是关于Go语言中接口(interface)及类型断言的详细教程,涵盖了接口的概念、定义、实现、使用注意事项以及类型断言的多种场景和方法。
38 4
下一篇
无影云桌面