为什么说Go的函数是“一等公民”?

开发 前端
这篇文章介绍了”一等公民“的定义和特性,并且通过案例论证了Go的函数是符合”一等公民“特性的。可以存储在变量中、可以作为参数传递给函数、可以在函数中创建并作为返回值从函数返回。

大家好,我是阳哥。

这期内容给大家分享一个很有意思的概念:Go语言中的“一等公民”。

有问必答

先安利一下我的「有问必答」栏目:

这周的主题是回答这位星友的提问:如何提高工作效率?

图片

大家有什么想聊的话题,想提的问题欢迎在评论区留言。

我每周六晚上8点都会在视频号直播,回答大家的留言和星球中的提问。

什么是一等公民?

我们先来看下相关概念

A language construct is said to be a FirstClass value in that language when there are no restrictions on how it can be created and used: when the construct can be treated as a value without restrictions.

翻译:如果对如何创建和使用它没有任何限制:当该结构可以被视为没有限制的值时,该语言结构被称为该语言中的 FirstClass 值。(即”一等公民“)

FirstClass features can be stored in variables, passed as arguments to functions, created within functions and returned from functions. In dynamically typed languages, a FirstClass feature can also have its type examined at run-time.

翻译:“一等公民”的特性是可以存储在变量中,可以作为参数传递给函数,可以在函数中创建并作为返回值从函数返回。

Go的函数满足了“一等公民”的特性定义,所以说Go的函数是”一等公民“。

下面带大家先了解下函数基本定义,然后再通过案例来论证下这些特性:

函数基本定义

func 函数名(参数)(返回值){
函数体
}
复制代码
  • 函数名:由字母、数字、下划线组合。注意数字不要作为开头;
  • 参数:非必填。可指定参数名称和类型,也可以使用可变参数...的写法,接收一个切片;
  • 返回值:非必填。只返回一个值时直接定义返回类型,返回多个值或者给返回值命名,这需要使用()和,进行定义。

简单示例:

func main() {
fmt.Println(sum(10, 20)) //30
fmt.Println(sum2()) //0
fmt.Println(sum2(10, 20)) //30
fmt.Println(sum3(100, 20)) //120
}

//指定参数
func sum(a, b int) int {
return a + b
}

//可变参数,num是个切片,接受0~n个参数
func sum2(num ...int) int {
ret := 0
for _, v := range num {
ret += v
}
return ret
}

//返回值命名
func sum3(a, b int) (ret int) {
ret = a + b
return
}
复制代码

特性1:可以存储在变量中

提供两种写法:

写法1:定义函数类型的变量

type calcFoo func(int, int) int //定义函数类型

func main() {
var add calcFoo
add = addFoo
fmt.Printf("type of c:%T\n", add) //type of c:main.calcFoo
fmt.Println(add(100, 200)) //300
}

func addFoo(a, b int) int {
return a + b
}
复制代码

备注:只要满足接收两个int​类型参数和返回一个int​类型值的函数,都可以认为是calcFoo类型的函数

写法2:使用匿名函数,赋值给变量(备注:匿名函数即没有函数名的函数,有两种使用方式)

//方式1:变量存储
add := func(a, b int) int {
return a + b
}
fmt.Println(add(100, 200)) //300

//方式2:直接执行
c := func(a, b int) int {
return a + b
}(22, 33)
fmt.Println(c) //55
复制代码

特性2:可以作为参数传递给函数

可以先定义好对应函数,也可以直接使用匿名函数,然后作为参数传递给函数

func main() {
//使用定义好的函数,进行传递
fmt.Println(addFoo2(11, 22, addFoo)) //33

//使用匿名函数,进行传递
fmt.Println(addFoo2(11, 22, func(a int, b int) int { return a + b })) //33
}

func addFoo(a, b int) int {
return a + b
}

func addFoo2(a, b int, foo func(int, int) int) int {
return foo(a, b)
}
复制代码

特性3:可以在函数中创建并作为返回值从函数返回

这个其实就是闭包的用法​,获取到返回来的func,然后传入参数,进行操作

func main() {
//例子1:
a1 := adder(10)
fmt.Println(a1(10), a1(20), a1(30)) //20 40 70

//例子2:
a2 := adder2()
fmt.Println(a2(10), a2(20), a2(30)) //10 30 60
a3 := adder2() //注意:a3是重新声明的,base被初始化为0,并不会沿用a2的base值,因为生命周期不同
fmt.Println(a3(10), a3(20), a3(30)) //10 30 60
}

func adder(base int) func(int) int {
return func(num int) int {
base += num
return base
}
}

func adder2() func(int) int {
var base int
return func(num int) int {
base += num
return base
}
}
复制代码

总结

这篇文章介绍了”一等公民“的定义和特性,并且通过案例论证了Go的函数是符合”一等公民“特性的。

可以存储在变量中、可以作为参数传递给函数、可以在函数中创建并作为返回值从函数返回。

使用好这些特性,可以让我们业务代码更加简洁,提高代码的健壮性和可读性。

本文转载自微信公众号「程序员升职加薪之旅」,作者「王中阳Go」,可以通过以下二维码关注。

转载本文请联系「 程序员升职加薪之旅」公众号。

责任编辑:武晓燕 来源: 程序员升职加薪之旅
相关推荐

2022-03-27 23:11:39

Go语言函数

2021-03-18 08:54:55

Go 语言函数

2021-01-27 05:25:44

Go语言函数

2022-11-07 18:12:54

Go语言函数

2015-04-27 09:48:46

Kubernetes数据中心

2023-05-29 08:03:41

代码Go语言

2022-03-14 08:33:09

TypeScriptJavaScript前端

2020-07-03 14:05:26

Serverless云服务商

2021-11-29 18:27:12

Web Wasmjs

2023-01-03 08:07:33

Go字符串指针

2023-05-05 16:26:33

2011-09-20 15:51:42

NoSQL

2011-10-27 13:37:51

网页设计

2022-05-10 09:53:45

数据治理数据开发DataOps

2016-06-13 17:22:27

火炬数据杨大海

2019-09-23 13:37:09

Anthos谷歌Kubernetes

2023-11-20 22:26:51

Go开发

2019-05-13 08:57:45

AIoTIOT智能

2019-09-23 13:10:02

容器进程

2018-01-02 10:14:14

CRM
点赞
收藏

51CTO技术栈公众号