在 Go 语言中,type 可以定义任何自定义的类型

比如熟悉的:type dog struct{},type myInt int 等等

所以 func 也是可以作为类型自定义的,type myFunc func(int) int,意思是自定义了一个叫 myFunc 的函数类型,这个函数的签名必须符合输入为 int,输出为 int

已知,相同底层类型的变量之间是可以相互转换的,例如从一个取值范围小的int16转为取值范围大的int32

所以,自定义的 myInt 和 int 之间也是可以转换的

1
2
3
4
5
6
7
8
type myInt int
 
func main() {
    var a int
    a = 2
    b := myInt(a)
    fmt.Println(b)    // 2
}

同理,myFunc 也是可以将签名为 func(int) int 的函数转换成 myFunc 类型

1
2
3
4
5
6
7
8
9
type myFunc func(int) int
 
func sum10(num int) int {
    fmt.Println(num*10)
}
 
func main() {
    newFunc := myFunc(sum10)
}

此时newFunc是一个变量,不是一个函数!!!

那么,这个变量有什么用?

回过头来想想,自定义的类型有什么用?

有什么场景需要自己定义一个 myInt 出来?就是重载原来的 int 类型,并自定义新的方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
type myInt int
 
func (mi myInt) IsZero() bool {
    return mi == 0
}
 
func main() {
    var a myInt
    a = 0
    fmt.Println(a.IsZero())        // true
}

同理,自定义函数类型也可以自定义方法

1
2
3
4
5
6
type myFunc func(int) int
 
func (mf myfunc) sum(a,b int) int {
    c := a + b
    return mf(c)
}

一个自定义函数类型的变量拥有了一个sum函数,有什么实际用途?

重点来了,有什么用途?

举个例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
type myFunc func(int) int
 
func (f myFunc) sum (a, b int) int {
    res := a + b
    return f(res)
}
 
func sum10(num int) int {
    return num * 10
}
 
func sum100(num int) int {
    return num * 100
}
 
func handlerSum(handler myFunc, a, b int) int {
    res := handler.sum(a, b)
    fmt.Println(res)
    return res
}
 
func main() {
    newFunc1 := myFunc(sum10)
    newFunc2 := myFunc(sum100)
 
    handlerSum(newFunc1, 1, 1)    // 20
    handlerSum(newFunc2, 1, 1)    // 200
}

解释下,假如 handlerSum 是一种特殊的 sum 算法,但是又有一部分的计算是可以通过外部自定义函数来干预的,那么使用这种方式就很合。

再进一步,如何使得 handlerSum 函数更抽象化?

我必须传递一个 myFunc 类型的变量参数进来吗?参数是一个 interface 呢,一个拥有 sum 方法的 interface 是不是更通用?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
type sumable interface {
    sum(int, int) int
}
 
type myFunc func(int) int
 
func (f myFunc) sum (a, b int) int {
    res := a + b
    return f(res)
}
 
func sum10(num int) int {
    return num * 10
}
 
func sum100(num int) int {
    return num * 100
}
 
func handlerSum(handler sumable, a, b int) int {
    res := handler.sum(a, b)
    fmt.Println(res)
    return res
}
 
// icansum 实现了 sumable 接口
type icansum struct {
    name string
    res int
}
 
func (ics *icansum) sum(a, b int) int {
    ics.res = a + b
    return ics.res
}
 
func main() {
    newFunc1 := myFunc(sum10)
    newFunc2 := myFunc(sum100)
 
    handlerSum(newFunc1, 1, 1)    // 20
    handlerSum(newFunc2, 1, 1)    // 200
 
    ics := &icansum{"I can sum", 0}
    // 由于 icansum 实现了接口 sumable,所以 handlerSum 可以直接传入 ics 结构体
    handlerSum(ics, 1, 1)         // 2
}

这样 handlerSum 接收的是一个只要实现了sum接口的变量就可以了,可以是一个 struct 变量,也可以是一个自定义函数类型变量,只要变量继承实现了 sum 函数即可,这样就可以更自由的干预(自定义)handlerSum 函数需要的执行过程了。

 

import "fmt"

type Func func(string) string

type Testinterfacer interface {
ADDstr(str string) string

}


func Ftest(str string) string {
return str
}
func (f Func) ADDstr(str string) string {
return str

}

func main() {
var f Func = Ftest //f:=Func(Ftest)
fmt.Println(f.ADDstr("test"))
t:=Testinterfacer(f) //var t Testinterfacer = f
fmt.Println(t.ADDstr("cheyunhua"))

}
package main

import "fmt"

// Greeting function types
type Greeting func(name string) string

func (g Greeting) say(n string) {
    fmt.Println(g(n))
}

func english(name string) string {
    return "Hello, " + name
}

func main() {
    greet := Greeting(english)
    greet.say("World")
}