Golang 中函式作為值與型別(轉載)

wangchunbo發表於2020-11-12

在 Go 語言中,我們可以把函式作為一種變數,用 type 去定義它,那麼這個函式型別就可以作為值傳遞,甚至可以實現方法,這一特性是在太靈活了,有時候我們甚至可以利用這一特性進行型別轉換。作為值傳遞的條件是型別具有相同的引數以及相同的返回值。

函式的型別轉換

Go 語言的型別轉換基本格式如下:

type_name(expression)

舉個例子:

package main        import "fmt"        type CalculateType func(int, int) // 宣告瞭一個函式型別        // 該函式型別實現了一個方法    func (c *CalculateType) Serve() {      fmt.Println("我是一個函式型別")    }        // 加法函式    func add(a, b int) {      fmt.Println(a + b)    }        // 乘法函式    func mul(a, b int) {      fmt.Println(a * b)    }        func main() {      a := CalculateType(add) // 將add函式強制轉換成CalculateType型別      b := CalculateType(mul) // 將mul函式強制轉換成CalculateType型別      a(2, 3)      b(2, 3)      a.Serve()      b.Serve()    }        // 5    // 6    // 我是一個函式型別    // 我是一個函式型別

如上,宣告瞭一個 CalculateType 函式型別,並實現 Serve() 方法,並將擁有相同引數的 add 和 mul 強制轉換成 CalculateType 函式型別,同時這兩個函式都擁有了 CalculateType 函式型別的 Serve() 方法。

函式作引數傳遞

package main        import "fmt"        type CalculateType func(a, b int) int // 宣告瞭一個函式型別        // 加法函式    func add(a, b int) int {      return a + b    }        // 乘法函式    func mul(a, b int) int {      return a * b    }        func Calculate(a, b int, f CalculateType) int {      return f(a, b)    }        func main() {      a, b := 2, 3      fmt.Println(Calculate(a, b, add))      fmt.Println(Calculate(a, b, mul))    }    // 5    // 6

如上例子,Calculate 的 f 引數型別為 CalculateType,add 和 mul 函式具有和 CalculateType 函式型別相同的引數和返回值,因此可以將 add 和 mul 函式作為引數傳入 Calculate 函式中。

net/http 包原始碼例子

// HandleFunc registers the handler function for the given pattern    // in the DefaultServeMux.    // The documentation for ServeMux explains how patterns are matched.    func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {      DefaultServeMux.HandleFunc(pattern, handler)    }
// HandleFunc registers the handler function for the given pattern.    func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {      mux.Handle(pattern, HandlerFunc(handler))    }
type HandlerFunc func(ResponseWriter, *Request)        // ServeHTTP calls f(w, r).    func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {      f(w, r)    }

剛開始看到這段原始碼的時候,真的有點懵逼了,這段原始碼的目的是為了將我們的 Handler 強制實現 ServeHTTP() 方法,如下例子:

func sayHi(w http.ResponseWriter, r *http.Request) {      io.WriteString(w, "hi")    }        func main() {      http.HandlerFunc("/", sayHi)      http.ListenAndserve(":8080", nil)    }

因為 HandlerFunc 是一個函式型別,而 sayHi 函式擁有和 HandlerFunc 函式型別一樣的引數值,因此可以將 sayHi 強制轉換成 HandlerFunc,因此 sayHi 也擁有了 ServeHTTP() 方法,也就實現了 Handler 介面,同時,HandlerFunc 的 ServeHTTP 方法執行了它自己本身,也就是 sayHi 函式,這也就可以看出來了,sayHi 就是 Handler 被呼叫之後的執行結果。

blog.csdn.net/zchdjb/article/detai...

本作品採用《CC 協議》,轉載必須註明作者和本文連結
感謝關注 上海PHP自學中心-免費程式設計視訊教學|

相關文章