Go 语言的函数是“一等公民”?

简介: Go 语言的函数是“一等公民”?

介绍

在 Go 语言中,函数被称为“一等公民”。实际上,在其它编程语言中,也有此说法,例如 JavaScript。

什么是编程语言的“一等公民”?Ward Cunningham 的解释如下:

如果对如何创建和使用它没有任何限制:当该结构可以被视为没有限制的值时,该语言结构被称为该语言中的 FirstClass 值。

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 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 语言的函数是否符合“一等公民”的特性。

02

存储在变量中

Go 语言的函数可以作为变量的值,存储在变量中。

func main() {
 var hello = func(name string) { fmt.Printf("hello %s\n", name) }
 hello("gopher")
}

阅读上面这段代码,我们定义一个变量 hello,和一个匿名函数,将匿名函数赋值给变量 hello,我们可以通过变量调用该匿名函数。

03

作为参数传递给其他函数

Go 语言的函数可以作为参数,传递给其他函数。

func main() {
 area := Circle(5, areaOfCircle)
 fmt.Printf("area:%.2f\n", area)
 perimeter := Circle(5, perimeterOfCircle)
 fmt.Printf("perimeter:%.2f\n", perimeter)
}
func Circle(r float64, op func(float64) float64) float64 {
 return op(r)
}
func areaOfCircle(r float64) float64 {
 return math.Pi * r * r
}
func perimeterOfCircle(r float64) float64 {
 return 2 * math.Pi * r
}

阅读上面这段代码,我们定义三个函数,分别是 Circle、areaOfCircle 和 perimeterOfCircle,其中 areaOfCircle 和 perimeterOfCircle 作为 Circle 的参数,分别用于计算面积和周长。

04

可以在函数中创建,并作为返回值

Go 语言的函数可以在函数体中创建,并作为返回值从函数体中返回。

func main() {
 calcArea := CircleCalc("area")
 fmt.Println(calcArea(5))
 calcPerimeter := CircleCalc("perimeter")
 fmt.Println(calcPerimeter(5))
}
func CircleCalc(s string) func(float64) float64 {
 switch s {
 case "area":
  return func(r float64) float64 {
   return math.Pi * r * r
  }
 case "perimeter":
  return func(r float64) float64 {
   return 2 * math.Pi * r
  }
 default:
  return nil
 }
}

阅读上面这段代码,我们定义一个函数 CircleCalc,在其函数体中定义两个匿名函数,并将匿名函数作为返回值从函数体中返回。

05

总结

本文我们通过三段示例代码,证明 Go 语言中函数符合“一等公民”的特性,我们可以使用这些特性,使业务代码更加简洁。

关于自定义函数类型和闭包,我们在之前的文章中已经介绍过,限于篇幅,本文不再赘述,感兴趣读者朋友们,可以翻阅一下之前的文章。

推荐阅读:

Go 使用标准库 net/rpc 包

参考资料:

https://wiki.c2.com//?FirstClass 

https://en.wikipedia.org/wiki/First-class_function 

https://golangbot.com/first-class-functions/ 

https://dev.to/andyhaskell/basics-of-first-class-functions-in-go-d5p 

https://go.dev/doc/codewalk/functions/ 

https://levelup.gitconnected.com/first-class-functions-in-golang-ef2a5001bb4f 

https://stackoverflow.com/questions/4358031/first-class-functions-in-go 

https://livebook.manning.com/book/get-programming-with-go/chapter-14/ 

https://dave.cheney.net/2016/11/13/do-not-fear-first-class-functions 


目录
相关文章
|
6月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
355 2
|
编译器 Go
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
|
运维 监控 算法
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
|
7月前
|
存储 Java Go
对比Java学习Go——函数、集合和OOP
Go语言的函数支持声明与调用,具备多返回值、命名返回值等特性,结合`func`关键字与类型后置语法,使函数定义简洁直观。函数可作为一等公民传递、赋值或作为参数,支持匿名函数与闭包。Go通过组合与接口实现面向对象编程,结构体定义数据,方法定义行为,接口实现多态,体现了Go语言的简洁与高效设计。
226 4
|
8月前
|
Cloud Native 安全 Java
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
525 1
|
8月前
|
Cloud Native Go API
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
551 0
|
8月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
374 0
|
8月前
|
Cloud Native Java 中间件
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
430 0
|
8月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
478 0
|
8月前
|
数据采集 Go API
Go语言实战案例:多协程并发下载网页内容
本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,讲解如何使用 Goroutine 和 Channel 实现多协程并发抓取网页内容,提升网络请求效率。通过实战掌握高并发编程技巧,构建爬虫、内容聚合器等工具,涵盖 WaitGroup、超时控制、错误处理等核心知识点。

热门文章

最新文章

下一篇
开通oss服务