網(wǎng)站首頁 編程語言 正文
在net/http包中,有一個接口型函數(shù)的實(shí)現(xiàn):
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) }
為什么在多路復(fù)用器中不能直接根據(jù)路由取到視圖函數(shù)HandlerFunc然后加括號執(zhí)行呢?
反而還要多此一舉實(shí)現(xiàn)Handler接口,然后將函數(shù)包裝后HandlerFunc(f).ServeHTTP(w,r)調(diào)用呢。
價(jià)值
既能夠?qū)⑵胀ǖ暮瘮?shù)類型(需類型轉(zhuǎn)換)作為參數(shù),也可以將結(jié)構(gòu)體作為參數(shù),使用更為靈活,可讀性也更好,這就是接口型函數(shù)的價(jià)值。
實(shí)例1(net/http)
可以 http.Handle 來映射請求路徑和處理函數(shù),Handle 的定義如下:
func Handle(pattern string, handler Handler)
第二個參數(shù)是即接口類型 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->默認(rèn)的多路復(fù)用器會調(diào)用它的ServeHTTP()方法 ?? ?_ = http.ListenAndServe("localhost:8000", nil) }
另外一個函數(shù) http.HandleFunc,HandleFunc 的定義如下:
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
第二個參數(shù)是一個普通的函數(shù)類型,
func main() { ?? ?http.HandleFunc("/home", home) ?? ?_ = http.ListenAndServe("localhost:8000", nil) }
兩種寫法是完全等價(jià)的,HandleFunc內(nèi)部將第二種寫法轉(zhuǎn)換為了第一種寫法。
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { ?? ?if handler == nil { ?? ??? ?panic("http: nil handler") ?? ?} ?? ?mux.Handle(pattern, HandlerFunc(handler)) }
http.ListenAndServe 的第二個參數(shù)也是接口類型 Handler,使用了標(biāo)準(zhǔn)庫 net/http 內(nèi)置的路由,因此傳入的值是 nil。
如果這個地方傳入的是一個實(shí)現(xiàn)了 Handler 接口的結(jié)構(gòu)體,就可以完全托管所有的 HTTP 請求,后續(xù)怎么路由,怎么處理,請求前后增加什么功能,都可以自定義了。慢慢地,就變成了一個功能豐富的 Web 框架了。
實(shí)例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) }
假設(shè)有一個方法:
func GetData(getter Getter, key string) []byte { ?? ?buf, err := getter.Get(key) ?? ?if err == nil { ?? ??? ?return buf ?? ?} ?? ?return nil }
如何給該方法傳參呢?
方式一:GetterFunc 類型的函數(shù)作為參數(shù)(匿名函數(shù))
GetData(GetterFunc(func(key string) ([]byte, error) { ?? ?return []byte(key), nil }), "hello")
方式二:普通函數(shù)
func test(key string) ([]byte, error) { ?? ?return []byte(key), nil } func main() { ? ? GetData(GetterFunc(test), "hello") }
將 test 強(qiáng)制類型轉(zhuǎn)換為 GetterFunc,GetterFunc 實(shí)現(xiàn)了接口 Getter,是一個合法參數(shù)。這種方式適用于邏輯較為簡單的場景。
方式三:實(shí)現(xiàn)了 Getter 接口的結(jié)構(gòu)體作為參數(shù)
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 實(shí)現(xiàn)了接口 Getter,也是一個合法參數(shù)。這種方式適用于邏輯較為復(fù)雜的場景,如果對數(shù)據(jù)庫的操作需要很多信息,地址、用戶名、密碼,還有很多中間狀態(tài)需要保持,比如超時、重連、加鎖等等。這種情況下,更適合封裝為一個結(jié)構(gòu)體作為參數(shù)。
這樣,既能夠?qū)⑵胀ǖ暮瘮?shù)類型(需類型轉(zhuǎn)換)作為參數(shù),也可以將結(jié)構(gòu)體作為參數(shù),使用更為靈活,可讀性也更好,這就是接口型函數(shù)的價(jià)值。
總結(jié)
原文鏈接:https://blog.csdn.net/General_zy/article/details/128822178
相關(guān)推薦
- 2022-04-18 python函數(shù)的默認(rèn)參數(shù)請勿定義可變類型詳解_python
- 2022-01-20 關(guān)于 Symbol() 能不能當(dāng)作 key值使用
- 2022-06-29 在Oracle中使用正則表達(dá)式_oracle
- 2023-02-01 Python動態(tài)演示旋轉(zhuǎn)矩陣的作用詳解_python
- 2022-09-21 Python腳本開發(fā)中的命令行參數(shù)及傳參示例詳解_python
- 2022-09-25 自動微分----pytorch中的梯度運(yùn)算與反向傳播函數(shù)(預(yù)備知識)
- 2022-10-03 Observing?KVO?Key-Value基本使用原理示例詳解_IOS
- 2023-10-10 ant tree拖動排序 實(shí)現(xiàn)同級拖動 和 跨級拖動
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支