12 | 使用函数的正确姿势
该思维导图由 AI 生成,仅供参考
前导内容:函数是一等的公民
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了Go语言中函数类型的灵活运用,以及如何利用高阶函数和闭包实现模块化编程的技巧。首先强调了在Go语言中函数是一等公民的重要性,函数类型是一等的数据类型,可以作为普通值在函数间传递、赋值给变量等。接着,文章讨论了高阶函数的概念,即接受其他函数作为参数传入或将其他函数作为结果返回的函数。通过示例,展示了如何编写高阶函数,以及如何实现闭包。文章还介绍了如何使用函数类型进行模块化编程,以及如何利用函数类型实现独立逻辑组件的热替换。此外,还提到了函数传参的注意事项,强调了程序的稳定和安全。整体而言,本文为读者提供了深入了解Go语言函数类型运用的指导,以及如何利用函数式编程的技巧进行模块化编程的实践经验。
《Go 语言核心 36 讲》,新⼈⾸单¥59
全部留言(52)
- 最新
- 精选
- Geek_牛逼的人1.如果是进行一层修改,即数组的某个完整元素进行修改(指针变化),那么原有数组不变;如果进行二层修改,即数组中某个元素切片内的某个元素再进行修改(指针未改变),那么原有数据也会跟着改变,传参可以理解是浅copy,参数本身的指针是不同,但是元素指针相同,对元素指针所指向目的的操作会影响传参过程中的原始数据; 2.一般来说应该是复制的,传参和返回应该是一个对称的过程,本身对这一片内存数据的操作只发生在函数内部,脱离函数就应该脱离这块内存区域
作者回复: 对的。
2019-09-09376 - 小强表示看不懂闭包存在的意义,没有例子说明为啥要这玩意
作者回复: 闭包就像样板代码和模版类型一样,其中先写了一部分代码,并确定了一部分功能。然后,当接到我们输入的参数值之后,它就可以确定另外一部分功能了。或许你可以把闭包看成填空题的题干。 闭包的存在意思有三: 1. 提高某个功能的灵活性,可以让使用方提供一部分功能的实现。但却可以控制这一部分的大小。 2. 提供动态替换某个功能的部分实现的可能性。这里的关键在于动态。 3. 使得代码动态替换的粒度缩小到函数级别。相比之下,模版类型的动态替换粒度是实例级别的。
2020-06-16428 - RyuGou第一道题,显然是不会造成原来内容的修改呀 package main import "fmt" func main(){ complexArray := [3][]string{ []string{"d", "s", "f"}, []string{"a", "b", "c"}, []string{"e", "g", "h"}, } tryTest(complexArray) fmt.Println(complexArray) } func tryTest(array [3][]string){ array[1] = []string{"1", "2", "3"} return } 输出: [[d s f] [a b c] [e g h]]
作者回复: 因为数组的每个元素也会被复制,你这样赋值只会改变数组副本中的一个元素值而已。你直接改其中的切片的元素值就会影响到外边了。
2018-09-0726 - lixiaofeng总结 函数不仅能够封装代码,分割功能,解耦逻辑;还可以化身为普通的值,在函数之间传递,赋予变量,判断转换等 函数值可以成为能够被随意传播的独立逻辑组件(功能模块) 只要两个函数的参数列表和结果列表元素顺序及类型是一致的,我们就说他们是一样的函数(实现了相同函数类型的函数) 函数类型是引用类型 高姐函数: 把函数作为参数值传递 或者 函数的返回值是一个函数
作者回复: 嗯,总结得挺好的。严格来说不能算是化身,因为函数本来就是值。另外我鸡蛋里挑个骨头,是“高阶函数”。:)
2019-12-223 - 兔子高哈喽老师你好,我学go的反射是学的最乱的,反射可以拿到您好好讲一讲吗?然后最近看到了go新出的法案里说go 2.0会出泛型有考虑讲一下go的泛型吗?
作者回复: Go的泛型几年后才会推出,现在没必要讲啊。
2018-09-073 - 浩仔是程序员闭包函数跟Java中的lambda表达式是同个意思吗?
作者回复: Java官方不是说Lambda就相当于闭包吗?
2021-02-042 - 甜质粥老师,您把first class翻译成了“一等公民”,让人更加误解了,不如直接就称呼为first class,比如这个:https://golangbot.com/first-class-functions/
作者回复: 在很多编程语言里都这么叫啊,这已经是一个约定俗成的中文称呼了。
2020-11-101 - Yayu请教老师一个关于控制算法相关的内容。本文中提及的卫述语句,经常会在诸如参数检查的时候使用,如果我业务逻辑代码模块中有很多函数,每个函数的参数是个名为 xxrRequest 的结构体,那么我就要在每个函数里写大段大段的卫戍语句。有什么可行的办法可以优化这种写法吗?
作者回复: 把检查代码封装到结构体的方法中,或者统一到某一个检查专用的程序实体中。
2019-02-2021 - CrazyCodes函数真正拿到的参数值其实只是它们的副本,那么函数返回给调用方的结果值也会被复制吗? func main() { m := [3]int{} m[0] = 0 m[1] = 1 m[2] = 2 fmt.Printf("1-----%p \n", &m[0]) test(m) fmt.Println(m) } func test(a [3]int) [3]int { fmt.Printf("2-----%p \n", &a[0]) a[1] = 100 defer func() { fmt.Printf("3-----%p \n", &a[0]) }() return a } 输出结果是 1-----0x140000140f0 2-----0x14000014120 3-----0x14000014120 不知道这算不算返回值没有复制
作者回复: 你的1号打印的是m的指针,2号和3号打印的是传到test函数里的参数值的指针,指针变了,这没问题。但是,你在main函数最后`fmt.Println(m)`依然是在打印m啊(而且你在“输出结果”下面也没贴上)。你应该在最后打印test函数返回的值的指针。 函数返回给调用方的结果值也会被复制。
2023-11-18归属地:北京 - Geek_4becf0老师请问 闭包所引用的自由变量,在确定后,也发生了拷贝吧,就是闭包外的函数调用完成,释放内存会把参数释放掉,但闭包引用了该参数,所以需要拷贝一份?
作者回复: 自由变量肯定会被复制到堆上一份,因为它发生逃逸了(跨函数引用问题)。
2021-12-20