21 函数变量

函数变量

一 函数是第一等公民

go中函数在Go语言中属于“一等公民”,说白了就是可以把函数当变量一样去用,具体如下

1、可以声明函数类型的变量

2、可以赋值

3、可以当做另外一个函数的参数

4、可以当做另外一个函数的返回值

了解:高阶函数指的就是

​ 1、函数可以作为参数

​ 2、函数可以作为返回值

二 可以声明函数类型的变量

我们可以使用type关键字来定义一个函数类型,具体格式如下:

type calculation func(int,int) int

上面语句定义了一个calculation类型,它是一种函数类型,这种函数接收两个int类型的参数并且返回一个int类型的返回值,凡是满足该条件的函数都是calculation类型的函数,如下add和sub

func add(x, y int) int{
    return x + y
}
func sub(x, y int) int{
    return x - y
}

func main() {
    fmt.Printf("%T\n",add)  // func(int, int) int
    fmt.Printf("%T\n",sub)  // func(int, int) int
}

三 可以把函数赋值给变量

可以把函数赋值变量,前提是该变量是对应的函数类型

func main() {
    var c calculation     // 声明一个calculation类型的变量c
    c = add               // 把add赋值给变量c
    fmt.Printf("%T\n", c) // main.calculation
    fmt.Println(c(1, 2))  // 像调用add一样调用c

    f := add               // 将函数add赋值给变量f
    fmt.Printf("%T\n", f)  // func(int, int) int
    fmt.Println(f(10, 20)) // 像调用add一样调用f
}

注意:

函数的类型被称为函数的标识符。如果两个函数形式参数列表和返回值列表中的变量类型一一对应,那么这两个函数被认为有相同的类型和标识符。形参和返回值的变量名不影响函数标识符,也不影响它们是否可以以省略参数类型的形式表示。

// 如下test1与test2的参数名不同,但它们是相同的类型
func test1(x int, y int) (z float64) {
    fmt.Println(x,y)
    return 1.1
}

func test2(xxx int, yyy int) (zzz float64) {
    fmt.Println(xxx,yyy)
    return 1.1
}

func main() {
    fmt.Printf("%T\n",test1)  // func(int, int) float64
    fmt.Printf("%T\n",test2)  // func(int, int) float64

    var f func(int, int) float64
    f = test1
    f(1,2)

    f=test2
    f(10,20)
}

四 可以把函数作为参数

type calculation func(int, int) int

func add(x, y int) int {
    return x + y
}
func cal1(x, y int, op calculation) int {
    return op(x, y)
}

func cal2(x, y int, op func(x, y int) int) int { // 同上述cal1
    return op(x, y)
}

func main() {
    res1 := cal1(10, 20, add)
    fmt.Println(res1) // 30

    res2 := cal1(10, 20, add)
    fmt.Println(res2) // 30
}

五 可以把函数作为返回值

func do(s string) (func(int, int) int, error) {
    switch s {
    case "+":
        return add, nil
    case "-":
        return sub, nil
    default:
        err := errors.New("无法识别的运算符")
        return nil, err
    }
}

func main() {
    f,err:=do("-")
    fmt.Println(f,err)
    fmt.Println(f(111,222))
}

六 练习

基于函数是第一等公民这一特性,优雅地取代多分支if

func login()  {
    fmt.Println("要想生活过得去,身上必须背点绿")
}
func register()  {
    fmt.Println("要想生活过得好,头顶必须长点草")
}
func withdraw()  {
    fmt.Println("横批:绿毛小乌龟")
}

var funcSlice map[string]func()= map[string]func(){
    "登录":login,
    "注册":register,
    "提现":withdraw,
}

func main() {
    //var f func()
    var fname string
    fmt.Printf("请输入功能名: ")
    fmt.Scanln(&fname)

    f,ok:=funcSlice[fname]
    if ok{
        f()
    }else {
        fmt.Println("输入的功能不存在")
    }
}
上一篇
下一篇
Copyright © 2022 Egon的技术星球 egonlin.com 版权所有 帮助IT小伙伴学到真正的技术