• Go学习笔记 -- 函数和高阶函数


    Go 函数

    定义函数

    使用 func 关键词,第一个括号里面定义参数类型以及参数的标识符,第二个括号里面定义返回值类型。

    func print(contents string) (int, error) {
    	//打印字符串并返回打印的字节数。
    	return fmt.Println(contents)
    }
    
    • 1
    • 2
    • 3
    • 4

    函数特性

    • 支持不定参。
    • 支持多返回值。
    • 支持命名返回参数。
    • 不支持嵌套,同一个包内不能有两个相同名字的函数。
    • 不支持重载。
    • 不支默认参数。
    • 在 Go 中,函数也是一种类型,可以作为方法的入参或者返回结果。
    • 支持匿名函数和闭包。

    其中先简单了解一下基本的特性。

    支持不定参

    如下,print 函数有一个可以接受多个 string 入参。
    JAVA 里面的不定参类似,这其实相当于是接受一个 srting 类型的数组,但是这样的入参类型只能定义在函数的最后面。

    func print(contents ...string) (int, error) {
    	//打印字符串并返回打印的字节数。
    	return fmt.Println(contents)
    }
    func main() {
    	fmt.Println(print("11", "22"))
    }
    ------------------------------------------------------
    [11 22]
    8 <nil>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    支持多返回值和命名返回参数

    上面的例子就是一个多返回值的函数,同时我们还能命名函数返回值。
    返回的时候直接用 retun ,函数会自动将 counterr 返回回去。

    func print(contents ...string) (count int, err error) {
    	//接收打印的字节数和异常
    	count,err = fmt.Println(contents) 
    	return
    }
    func main() {
    	fmt.Println(print("11", "22"))
    }
    ------------------------------------------------------
    [11 22]
    8 <nil>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    不支持嵌套,不支持重载

    以下代码都提示异常
    文件①:/demo/demo_lib1.go

    package main
    import (
    	"fmt"
    )
    //提示异常: other declaration of print
    func print(sss int, contents ...string) (count int, err error) {
    	//打印字符串并返回打印的字节数。
    	count, err = fmt.Println(contents)
    	return
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    文件②:/demo/demo_main.go

    package main
    import (
    	"fmt"
    )
    //提示异常: other declaration of print
    func print(contents ...string) (count int, err error) {
    	//打印字符串并返回打印的字节数。
    	count, err = fmt.Println(contents)
    	return
    }
    func main() {
    	fmt.Println(print2("11", "22"))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    高阶函数

    上面我们提到,在 Go 中,函数可以作为另一个函数的入参或者返回结果。而以函数作为参数或者返回值的函数就称为高阶函数。
    高阶函数的条件,满足其一即可:

    1. 使用其他函数作为入参
    2. 把其他函数作为返回结果

    例如:
    下面的 calc 函数和 retFunc 函数都是高阶函数。

    type mathFunc func(x, y int) int
    
    func calc(x int, y int, mf mathFunc) (int, error) {
    	if mf == nil {
    		return 0, errors.New("invalid operation")
    	}
    	return mf(x, y), nil
    }
    
    func retFunc() mathFunc {
    	return func(x, y int) int {
    		return x + y
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    闭包

    什么是闭包

    闭包是可以包含自由变量的代码块,这些变量不在这个代码块内或者任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块为自由变量提供绑定的作用域。

    用代码来解释
    type mathFunc func(i int) int
    func operate2() mathFunc {
    	sum := 0
    	return func(j int) int {
    		sum += j
    		return sum 
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    其中 operate2 函数中返回的这个匿名函数,就形成了一个闭包。
    闭包中使用到了自由变量 sum ,这个 sum 是闭包函数所处函数环境中定义的,可以说匿名函数的功能被绑定在了变量 sum 上。

    addBase := operate2(1) //addBase 为所有传入的 int 加 1
    fmt.Println(addBase(2))
    -----------------------------
    3
    
    • 1
    • 2
    • 3
    • 4
    闭包的作用
    1. 延迟动态生成程序逻辑,我们可以根据需要生成功能不同的函数。
    2. 缩小变量作用域,减少对全局变量的污染
      在上面的例子中,我们其实实现了一个累加器,如果我们定义的是全局变量 sum ,有可能会被其他操作污染,而且当我们需要实现很多个累加器时,我们就需要定义很多个全局变量 sum 1…n
      但是我们使用闭包的方式,将累加值定义在函数中,缩小其作用域,使每个函数有自己独立的累加值,避免了累加值被其他操作污染的情况。
  • 相关阅读:
    Linux(六)NFS(network file system)服务器实验
    进程与线程的区别
    【PointNet—论文笔记分享】
    mPaas小程序(支付宝、钉钉...)自定义组件,组件传参
    产品经理就业喜报:有努力,回报就在眼前
    DGIOT国内首家轻量级物联网开源平台——MQTT接入实战教程
    SpringBoot通过配置读取json文件
    Primavera Unifier 21.12.4~21.12.7.0疑似漏洞
    Java的方法重载、变量和值传递
    使用一个Series序列减去另一个Series序列Series.subtract()
  • 原文地址:https://blog.csdn.net/qq_40096897/article/details/127918491