在 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") }