網站首頁 編程語言 正文
在net/http包中,有一個接口型函數的實現:
type Handler interface { ?? ?ServeHTTP(ResponseWriter, *Request) } // The HandlerFunc type is an adapter to allow the use of // ordinary functions as HTTP handlers. If f is a function // with the appropriate signature, HandlerFunc(f) is a // Handler that calls f. type HandlerFunc func(ResponseWriter, *Request) // ServeHTTP calls f(w, r). func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { ?? ?f(w, r) }
為什么在多路復用器中不能直接根據路由取到視圖函數HandlerFunc然后加括號執行呢?
反而還要多此一舉實現Handler接口,然后將函數包裝后HandlerFunc(f).ServeHTTP(w,r)調用呢。
價值
既能夠將普通的函數類型(需類型轉換)作為參數,也可以將結構體作為參數,使用更為靈活,可讀性也更好,這就是接口型函數的價值。
實例1(net/http)
可以 http.Handle 來映射請求路徑和處理函數,Handle 的定義如下:
func Handle(pattern string, handler Handler)
第二個參數是即接口類型 Handler,
func home(w http.ResponseWriter, r *http.Request) { ?? ?w.WriteHeader(http.StatusOK) ?? ?_, _ = w.Write([]byte("hello, index page")) } func main() { ?? ?http.Handle("/home", http.HandlerFunc(home)) ?? ?// http.HandlerFunc(home)->HandlerFunc->默認的多路復用器會調用它的ServeHTTP()方法 ?? ?_ = http.ListenAndServe("localhost:8000", nil) }
另外一個函數 http.HandleFunc,HandleFunc 的定義如下:
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
第二個參數是一個普通的函數類型,
func main() { ?? ?http.HandleFunc("/home", home) ?? ?_ = http.ListenAndServe("localhost:8000", nil) }
兩種寫法是完全等價的,HandleFunc內部將第二種寫法轉換為了第一種寫法。
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { ?? ?if handler == nil { ?? ??? ?panic("http: nil handler") ?? ?} ?? ?mux.Handle(pattern, HandlerFunc(handler)) }
http.ListenAndServe 的第二個參數也是接口類型 Handler,使用了標準庫 net/http 內置的路由,因此傳入的值是 nil。
如果這個地方傳入的是一個實現了 Handler 接口的結構體,就可以完全托管所有的 HTTP 請求,后續怎么路由,怎么處理,請求前后增加什么功能,都可以自定義了。慢慢地,就變成了一個功能豐富的 Web 框架了。
實例2(tutu)
// A Getter loads data for a key. type Getter interface { ?? ?Get(key string) ([]byte, error) } // A GetterFunc implements Getter with a function. type GetterFunc func(key string) ([]byte, error) // Get implements Getter interface function func (f GetterFunc) Get(key string) ([]byte, error) { ?? ?return f(key) }
假設有一個方法:
func GetData(getter Getter, key string) []byte { ?? ?buf, err := getter.Get(key) ?? ?if err == nil { ?? ??? ?return buf ?? ?} ?? ?return nil }
如何給該方法傳參呢?
方式一:GetterFunc 類型的函數作為參數(匿名函數)
GetData(GetterFunc(func(key string) ([]byte, error) { ?? ?return []byte(key), nil }), "hello")
方式二:普通函數
func test(key string) ([]byte, error) { ?? ?return []byte(key), nil } func main() { ? ? GetData(GetterFunc(test), "hello") }
將 test 強制類型轉換為 GetterFunc,GetterFunc 實現了接口 Getter,是一個合法參數。這種方式適用于邏輯較為簡單的場景。
方式三:實現了 Getter 接口的結構體作為參數
type DB struct{ url string} func (db *DB) Query(sql string, args ...string) string { ?? ?// ... ?? ?return "hello" } func (db *DB) Get(key string) ([]byte, error) { ?? ?// ... ?? ?v := db.Query("SELECT NAME FROM TABLE WHEN NAME= ?", key) ?? ?return []byte(v), nil } func main() { ?? ?GetData(new(DB), "hello") }
DB 實現了接口 Getter,也是一個合法參數。這種方式適用于邏輯較為復雜的場景,如果對數據庫的操作需要很多信息,地址、用戶名、密碼,還有很多中間狀態需要保持,比如超時、重連、加鎖等等。這種情況下,更適合封裝為一個結構體作為參數。
這樣,既能夠將普通的函數類型(需類型轉換)作為參數,也可以將結構體作為參數,使用更為靈活,可讀性也更好,這就是接口型函數的價值。
總結
原文鏈接:https://blog.csdn.net/General_zy/article/details/128822178
相關推薦
- 2022-12-09 Python命名空間與作用域深入全面詳解_python
- 2022-12-10 Android入門之TextClock的使用教程_Android
- 2024-03-14 SpringBoot中事務
- 2023-08-28 react:使用 moment 來獲取日期
- 2022-05-21 Python集合set()使用的方法詳解_python
- 2022-10-11 app:transformClassesAndResourcesWithProguardForRel
- 2022-04-17 解決activiti7的懶加載機制無法將Task結果直接返回
- 2022-12-16 python靜態web服務器實現方法及代碼詳解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支