1. 程式人生 > 其它 >Go語言的type func()用法

Go語言的type func()用法

http://www.manoner.com/post/GoLand/Go%E8%AF%AD%E8%A8%80%E7%9A%84type-func%E7%94%A8%E6%B3%95/

|閱讀

在 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 函式需要的執行過程了。