一文带你探索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语言函数的资料请关注脚本之家其它相关文章!

相关文章

  • 使用go module导入本地包的方法教程详解

    使用go module导入本地包的方法教程详解

    go module 将是Go语言默认的依赖管理工具。到今天 Go1.14 版本推出之后 Go modules 功能已经被正式推荐在生产环境下使用了。本文重点给大家介绍如何使用 go module 导入本地包,感兴趣的朋友一起看看吧
    2020-03-03
  • Go语言标准库之strconv的使用

    Go语言标准库之strconv的使用

    本文主要介绍了Go语言标准库之strconv的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Go语言中的Base64编码原理介绍以及使用

    Go语言中的Base64编码原理介绍以及使用

    Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,可用于在HTTP环境下传递较长的标识信息,下面这篇文章主要给大家介绍了关于Go语言中的Base64编码原理介绍以及使用的相关资料,需要的朋友可以参考下
    2022-01-01
  • Go语言基础函数基本用法及示例详解

    Go语言基础函数基本用法及示例详解

    这篇文章主要为大家介绍了Go语言基础函数基本用法及示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2021-11-11
  • Go使用sync.Map来解决map的并发操作问题

    Go使用sync.Map来解决map的并发操作问题

    在 Golang 中 map 不是并发安全的,sync.Map 的引入确实解决了 map 的并发安全问题,本文就详细的介绍一下如何使用,感兴趣的可以了解一下
    2021-10-10
  • Golang中map数据类型的使用方法

    Golang中map数据类型的使用方法

    这篇文章主要介绍了Golang中map数据类型的使用方法,文章围绕主题展开详细的内容戒杀,具有一定的参考价值,需要的朋友可以参考一下
    2022-09-09
  • 秒懂Golang匿名函数

    秒懂Golang匿名函数

    所谓匿名函数,就是没有名字的函数,本文重点给大家介绍Golang匿名函数的相关知识,通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • Golang urfave/cli库简单应用示例详解

    Golang urfave/cli库简单应用示例详解

    这篇文章主要为大家介绍了Golang urfave/cli库简单应用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Go语言append切片添加元素的实现

    Go语言append切片添加元素的实现

    本文主要介绍了Go语言append切片添加元素的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • go性能分析工具pprof的用途及使用详解

    go性能分析工具pprof的用途及使用详解

    刚开始接触go就遇到了一个内存问题,在进行内存分析的时候发现了一下比较好的工具,在此留下记录,下面这篇文章主要给大家介绍了关于go性能分析工具pprof的用途及使用的相关资料,需要的朋友可以参考下
    2023-01-01

最新评论