一文带你探索Go语言中的函数一等公民

 更新时间:2023年07月19日 08:23:53   作者:Go技术干货  
你是否听说过 Go 语言中的函数是一等公民,如果没有,那么恭喜你,本文将带你一起揭开这个神秘的面纱,感兴趣的小伙伴快来和小编一起学习起来吧

前言

你是否听说过 Go 语言中的函数是一等公民?如果没有,那么恭喜你,本文将带你一起揭开这个神秘的面纱。如果你已经了解这个概念,你是否知道为什么 Go 语言中的函数被称为一等公民?不管你的答案是什么,通过阅读本文,你将对这个概念有更深入的了解。

准备好了吗?准备一杯你最喜欢的咖啡或茶,随着本文一探究竟吧。

一等公民

In a given programming language design, a first-class citizen is an entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument, returned from a function, and assigned to a variable.

什么是一等公民?上面引文来自维基百科,直译过来的意思是:“在给定的编程语言设计中,一等公民是指支持所有通常可用于其他实体的操作的实体。这些操作通常包括作为参数传递、从函数返回和赋值给变量。”。

直译过来似乎有点难以理解,没关系,我们可以用更简单的方式来理解:“在编程语言设计中,被称为一等公民的元素可以自由地进行常见的操作,如作为参数传递、从函数返回和赋值给变量”。

在 Go 语言中,函数具备这些特性,可以赋值给变量、作为参数传递,并且可以作为函数的返回值。

函数作为一等公民的实际运用示例

当我们理解了 Go 语言中的函数为什么被视为一等公民之后,让我们来探索一下它作为一等公民的实际运用吧。

赋值给变量

在 Go 语言中,函数是一种类型,它可以像其他类型(如 int64string 等)一样被赋值给变量,这意味着我们可以创建一个变量,将函数赋值给它,然后通过该变量来调用函数。

将普通函数赋值给变量

我们可以将普通函数赋值给变量,以便通过变量调用该函数。下面是一个示例代码:

import (
	"fmt"
)
func SayHello(s string) {
	fmt.Println(s)
}
func main() {
	sayHelloFunc := SayHello
	sayHelloFunc("你好,我是陈明勇") // 你好,我是陈明勇
}

在上面的例子中,首先我们定义了一个普通函数 SayHello(s string),该函数接受一个字符串参数 s,并在函数体中使用 fmt.Println 函数打印字符串;

然后在 main 函数中,我们将该函数赋值给变量 sayHelloFunc,通过这个变量,我们可以调用 SayHello 函数,实现相同的功能。这种方式可以在需要动态选择函数的情况下使用,使得代码更加 灵活 和 可复用

创建匿名函数并赋值给变量

除了将普通函数赋值给变量,我们还可以通过创建匿名函数的形式并将其赋值给变量。下面是一个示例代码:

import (
	"fmt"
)
func main() {
	sayHelloFunc := func(s string) {
		fmt.Println(s)
	}
	sayHelloFunc("你好,我是陈明勇") // 你好,我是陈明勇
}

在上述代码中,我们使用 func 关键字创建了一个匿名函数,该函数也是接受一个字符串参数 s,并在函数体中使用 fmt.Println 函数打印字符串;然后,我们将该匿名函数赋值给 sayHelloFunc 变量。通过 sayHelloFunc 变量,我们可以调用匿名函数并传入相应的参数,实现相同的功能。

匿名函数的创建方式灵活且简洁,特别适用于一次性的函数需求或需要在不同的上下文中定义函数的场景。

作为参数传递

在 Go 语言中,函数可以作为函数参数传递给其他函数,这使得函数可以更加灵活的操作和组合。我们来看看一个时间转换的例子;

import (
	"fmt"
	"time"
)
// ApplyFormatTimeToStringFunc 根据参数 t 和 operation,将时间类型转成对应格式的字符串类型,字符串的格式由参数 operation 决定
// 如果参数 t 为零值,则返回空字符串
func ApplyFormatTimeToStringFunc(t time.Time, operation func(t time.Time) string) string {
	if t.IsZero() {
		return""
	}
	return operation(t)
}
// FormatTimeToString 将时间转成 yyyy-MM-dd 的形式
func FormatTimeToString(t time.Time) string {
	return t.Format(time.DateOnly)
}
// FormatDateTimeToString 将时间转成 yyyy-MM-dd HH:mm:ss 的形式
func FormatDateTimeToString(t time.Time) string {
	return t.Format(time.DateTime)
}
func main() {
	// yyyy-MM-dd
	formatTimeToString := ApplyFormatTimeToStringFunc(time.Now(), FormatTimeToString)
	fmt.Println(formatTimeToString) // 2023-07-18
	// yyyy-MM-dd HH:mm:ss
	formatDateTimeToString := ApplyFormatTimeToStringFunc(time.Now(), FormatDateTimeToString)
	fmt.Println(formatDateTimeToString) // 2023-07-18 00:00:00
}

在上述例子中,首先我们定义了一个 ApplyFormatTimeToStringFunc 函数,该函数接收一个时间类型参数 t 和一个函数类型参数 operation,根据参数 t 和 operation,将时间类型转成字符串类型,字符串的格式由参数 operation 决定;

然后定义两个操作函数 FormatTimeToString 和 FormatDateTimeToString,这两个函数分别将时间转换为 yyyy-MM-dd 和 yyyy-MM-dd HH:mm:ss 的格式;

最后在 main 函数中,我们通过将不同的操作函数作为参数传递给 ApplyFormatTimeToStringFunc 函数来格式化当前时间。通过使用函数作为参数传递给另一个函数,动态改变函数的行为,使得我们可以根据需要选择不同的格式化方式来处理时间,提高代码的灵活性和可复用性。

作为函数的返回值

在 Go 语言中,函数除了可以赋值给变量和作为参数进行传递以外,它还可以作为函数的返回值进行使用。以下是示例代码:

import (
	"fmt"
)
func CreateDialogueFormatter(name string) func(string) string {
	returnfunc(s string) string {
		return fmt.Sprintf("[%s]: ", name) + s
	}
}
func main() {
	DialogueOfCmy := CreateDialogueFormatter("陈明勇")
	fmt.Println(DialogueOfCmy("你好")) // [陈明勇]: 你好
	DialogueOfGopher := CreateDialogueFormatter("Gopher")
	fmt.Println(DialogueOfGopher("你好")) // [Gopher]: 你好
}

在上面的例子中,首先我们定义了 CreateDialogueFormatter 函数,该函数接收一个 name 参数,用于设置对话人昵称,并返回一个可定制化的对话函数;

然后在 main 函数中,通过调用 CreateDialogueFormatter 函数并传入不同的昵称,可以创建多个针对不同对话人的对话函数。

通过将函数作为返回值,我们可以在运行时动态地生成函数,从而使函数更具灵活性和可定制性。

小结

函数作为一等公民在 Go 语言中非常重要,借助其三大特性,我们能够实现高阶函数编程,提升代码的灵活性和可复用性。

以上就是一文带你探索Go语言中的函数一等公民的详细内容,更多关于Go语言函数的资料请关注脚本之家其它相关文章!

相关文章

  • golang 跳出多重循环的高级break用法说明

    golang 跳出多重循环的高级break用法说明

    这篇文章主要介绍了golang 跳出多重循环的高级break用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • golang实现简单rpc调用过程解析

    golang实现简单rpc调用过程解析

    这篇文章主要介绍了golang实现简单rpc调用,包括RPC具体实现结合实例代码给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • 教你一招完美解决vscode安装go插件失败问题

    教你一招完美解决vscode安装go插件失败问题

    VSCode是我们开发go程序的常用工具,但是安装VSCode成功后,创建一个.go文件居然提示错误了,所以下面下面这篇文章主要给大家介绍了如何通过一招完美解决vscode安装go插件失败问题的相关资料,需要的朋友可以参考下
    2022-07-07
  • golang debug调试的实现

    golang debug调试的实现

    本文主要介绍了使用Go语言进行本地调试和远程调试,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-12-12
  • golang JSON技巧小结

    golang JSON技巧小结

    本文介绍了在Go语言中使用JSON时的一些小技巧,包括如何将字符串转换为数字、临时忽略空字段、临时添加额外字段、粘合两个struct、改名struct字段、支持不同类型的数字,感兴趣的朋友跟随小编一起看看吧
    2024-11-11
  • Golang实现定时任务的几种方法小结

    Golang实现定时任务的几种方法小结

    在 Golang 开发中,定时任务是常见的需求,本文将介绍几种在 Golang 中实现定时任务的方法,包括 time 包的定时器、ticker,以及第三方库 cron,并通过示例代码展示它们的使用方式,需要的朋友可以参考下
    2024-01-01
  • Go语言包管理工具Godep的用法

    Go语言包管理工具Godep的用法

    这篇文章介绍了Go语言包管理工具Godep的用法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Go使用Redis实现分布式锁的常见方法

    Go使用Redis实现分布式锁的常见方法

    Redis 提供了一些原语,可以帮助我们实现高效的分布式锁,下边是使用 Redis 实现分布式锁的一种常见方法,通过代码示例给大家介绍的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2024-11-11
  • golang使用go mod导入本地包和第三方包的方式

    golang使用go mod导入本地包和第三方包的方式

    这篇文章主要介绍了golang使用go mod导入本地包和第三方包的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • 基于HLS创建Golang视频流服务器的优缺点

    基于HLS创建Golang视频流服务器的优缺点

    HLS 是 HTTP Live Streaming 的缩写,是苹果开发的一种基于 HTTP 的自适应比特率流媒体传输协议。这篇文章主要介绍了基于 HLS 创建 Golang 视频流服务器,需要的朋友可以参考下
    2021-08-08

最新评论