欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go標準庫-ServeMux的使用與模式匹配深入探究

 更新時間:2024年01月15日 10:53:09   作者:涼涼的知識庫  
這篇文章主要為大家介紹了Go標準庫-ServeMux的使用與模式匹配深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

本篇為【深入理解Go標準庫】系列第二篇

第一篇:http server的啟動

第二篇:ServeMux的使用與模式匹配??

根據(jù) Golang 文檔 中的介紹,ServeMux是一個 HTTP 請求多路復用器(HTTP Request multiplexer)。它按照一定規(guī)則匹配請求URL和已注冊的模式,并執(zhí)行其中最匹配的模式的Handler

如果你還不知道什么是Handler,強烈建議你先閱讀下:第一篇:http server的啟動

基本使用

http.ServeMux實現(xiàn)了Handler接口

type Handler interface {
 ServeHTTP(ResponseWriter, *Request)
}

http.ServeMux提供兩個函數(shù)用于注冊不同Path的處理函數(shù)

  • ServeMux.Handle 接收的是Handler接口實現(xiàn)

  • ServeMux.HandleFunc 接收的是匿名函數(shù)

type PathBar struct {
}

func (m PathBar) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 w.Write([]byte("Receive path bar"))
 return
}

func main() {
 mx := http.NewServeMux()

 mx.Handle("/bar/", PathBar{})
 mx.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
  w.Write([]byte("Receive path foo"))
 })

 http.ListenAndServe(":8009", mx)
}

?? 通過類型轉(zhuǎn)換實現(xiàn)接口

值得一提的是ServeMux.HandleFunc的實現(xiàn),底層還是調(diào)用了ServeMux.Handle

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
 if handler == nil {
  panic("http: nil handler")
 }
 mux.Handle(pattern, HandlerFunc(handler))
}

HandlerFunc(handler)這里并不是函數(shù)調(diào)用,而是類型轉(zhuǎn)換

type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
 f(w, r)
}

通過把handler func(ResponseWriter, *Request)轉(zhuǎn)換成類型HandlerFunc,而類型HandlerFunc實現(xiàn)了Handler接口

?? 全局默認值

當沒有設置http.Server.Handler屬性時,http.Server就會使用一個全局的變量DefaultServeMux *ServeMux來作為http.Server.Handler的值

下面的代碼和上面的沒有區(qū)別

func main() {
 http.Handle("/bar/", PathBar{})
 http.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
  w.Write([]byte("Receive path foo"))
 })

 http.ListenAndServe(":8009", nil)
}

Pattern匹配

預處理

預處理的是請求的url,以方便匹配,在注冊時是不會做任何處理的

  • 移除host中的端口號

  • 針對 URL 中包含..或者.的請求,ServeMux 會對其 Path 進行整理,并匹配到合適的路由模式上

  • 針對 URL 中包含重復/的請求,ServeMux 會對其進行重定向

func main() {
 mx := http.NewServeMux()

 mx.HandleFunc("/abc/def", func(writer http.ResponseWriter, request *http.Request) {
  fmt.Fprintln(writer, request.Host, request.URL.Path)
 })

 http.ListenAndServe(":8009", mx)
}

?? 預處理的是請求的url

pattern是不會被處理的,而請求的url都是被處理成標準格式

所以如果注冊如下的pattern,無論如何也是無法被命中的

func main() {
 mx := http.NewServeMux()

 mx.HandleFunc("/abc//def", func(writer http.ResponseWriter, request *http.Request) {
  fmt.Fprintln(writer, request.Host, request.URL.Path)
 })
}

無論是/abc/def還是/abc//def都無法被命中

$ curl 127.0.0.1:8009/abc/def
404 page not found
$ curl 127.0.0.1:8009/abc//def
<a href="/abc/def" rel="external nofollow"  rel="external nofollow"     >Moved Permanently</a>.

?? 帶 ..或者.請求與重復/請求的處理不同

包含..或者.整理之后匹配到合適的路由模式上,并不會重定向

$ curl  127.0.0.1:8009/ccc/../abc/./def
127.0.0.1:8009 /abc/def

含重復/,會重定向

$ curl -v  127.0.0.1:8009/abc//def
*   Trying 127.0.0.1:8009...
* Connected to 127.0.0.1 (127.0.0.1) port 8009 (#0)
> GET /abc//def HTTP/1.1
> Host: 127.0.0.1:8009
> User-Agent: curl/7.79.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Content-Type: text/html; charset=utf-8
< Location: /abc/def
< Date: Thu, 10 Nov 2022 16:05:13 GMT
< Content-Length: 43
< 
<a href="/abc/def" rel="external nofollow"  rel="external nofollow"     >Moved Permanently</a>.

* Connection #0 to host 127.0.0.1 left intact

路徑匹配

ServeMux 注冊路由模式的方式有兩種,固定根路徑例如"/favicon.ico",與以根路徑開始的子樹,例如"/images/"

?? 固定路徑(fixed, rooted paths)

固定根路徑就是指定一個固定的 URL 和請求進行精確匹配

?? 以根路徑開始的子樹(rooted subtrees)

以根路徑開始的子樹是符合最長路徑匹配的原則的,例如我們注冊了兩個子路徑,/image/gif//image/,URL 為/image/gif/的請求會優(yōu)先匹配第一個路由模式,其他路徑會匹配/image/

?? 注意:

1、凡是/結(jié)尾的路徑都被看作以根路徑開始的子樹,因此 / 也被看作以根路徑開始的子樹,它不僅匹配/,而且也會匹配所有未被其他路由模式匹配的請求。

func main() {
 mx := http.NewServeMux()

 mx.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
  fmt.Fprintln(writer, request.URL.EscapedPath())
 })

 http.ListenAndServe(":8009", mx)
}
$ curl 127.0.0.1:8009/abc
/abc

2、如果只注冊了一個子樹路徑(/結(jié)尾)并且請求URL沒有/結(jié)尾,ServeMux會返回重定向。如果再增加一個沒有/結(jié)尾的模式的話,就會精確匹配,也就不會有這種行為了

例如我們只注冊了子路徑/abc/,服務器會自動將/abc請求重定向為/abc/。

func main() {
 mx := http.NewServeMux()
 mx.HandleFunc("/abc/", func(writer http.ResponseWriter, request *http.Request) {
  fmt.Fprintln(writer, request.URL.EscapedPath())
 })
 http.ListenAndServe(":8009", mx)
}
$ curl -v 127.0.0.1:8009/abc
*   Trying 127.0.0.1:8009...
* Connected to 127.0.0.1 (127.0.0.1) port 8009 (#0)
> GET /abc HTTP/1.1
> Host: 127.0.0.1:8009
> User-Agent: curl/7.79.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Content-Type: text/html; charset=utf-8
< Location: /abc/
< Date: Thu, 10 Nov 2022 15:30:13 GMT
< Content-Length: 40
< 
<a href="/abc/" rel="external nofollow"   >Moved Permanently</a>.

* Connection #0 to host 127.0.0.1 left intact

如果我們不想讓服務器自動重定向的話,只需要再添加一個/abc模式就好了

func main() {
 mx := http.NewServeMux()

 mx.HandleFunc("/abc/", func(writer http.ResponseWriter, request *http.Request) {
  fmt.Fprintln(writer, request.URL.EscapedPath())
 })

 mx.HandleFunc("/abc", func(writer http.ResponseWriter, request *http.Request) {
  fmt.Fprintln(writer, request.URL.EscapedPath())
 })

 http.ListenAndServe(":8009", mx)
}
$ curl  127.0.0.1:8009/abc 
/abc

域名匹配(Host-specific patterns)

ServeMux 還支持根據(jù)主機名精確匹配,匹配時會嚴格匹配host,path的匹配則還遵循上面的原則

?? 注意:

有域名的優(yōu)先級會更高,所以可以注冊一個帶域名的路徑和不帶域名的路徑

func main() {
 mx := http.NewServeMux()

 mx.HandleFunc("example01.com/abc/",
  func(writer http.ResponseWriter, request *http.Request) {
   fmt.Fprintln(writer, request.Host, request.URL.EscapedPath())
  })

 mx.HandleFunc("/abc/", func(writer http.ResponseWriter, request *http.Request) {
  fmt.Fprintln(writer, request.Host, request.URL.EscapedPath())
 })

 http.ListenAndServe(":8009", mx)
}

example01.com會匹配第一個handler,其他域名則匹配第二個

$ curl -H 'HOST:example01.com'  127.0.0.1:8009/abc/
example01.com /abc/

$ curl -H 'HOST:example02.com'  127.0.0.1:8009/abc 
example02.com /abc

Method和路徑參數(shù)匹配(method, path specificity patterns)

最新的特性還在討論中,大致的patterns會像下面這樣

https://github.com/golang/go/discussions/60227 

/item/
POST /item/{user}
/item/{user}
/item/{user}/{id}
/item/{$}
POST alt.com/item/{user}

以上就是Go標準庫-ServeMux的使用與模式匹配深入探究的詳細內(nèi)容,更多關(guān)于Go ServeMux模式匹配的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • golang進行簡單權(quán)限認證的實現(xiàn)

    golang進行簡單權(quán)限認證的實現(xiàn)

    本文主要介紹了golang簡單權(quán)限認證的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • go?sync?Waitgroup數(shù)據(jù)結(jié)構(gòu)實現(xiàn)基本操作詳解

    go?sync?Waitgroup數(shù)據(jù)結(jié)構(gòu)實現(xiàn)基本操作詳解

    這篇文章主要為大家介紹了go?sync?Waitgroup數(shù)據(jù)結(jié)構(gòu)實現(xiàn)基本操作詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • Ubuntu18.04 LTS搭建GO語言開發(fā)環(huán)境過程解析

    Ubuntu18.04 LTS搭建GO語言開發(fā)環(huán)境過程解析

    這篇文章主要介紹了Ubuntu18.04 LTS搭建GO語言開發(fā)環(huán)境過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • 從零封裝Gin框架及項目初始化教程

    從零封裝Gin框架及項目初始化教程

    這篇文章主要為大家介紹了從零封裝Gin框架及項目的初始化教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • Golang結(jié)構(gòu)化日志包log/slog的使用詳解

    Golang結(jié)構(gòu)化日志包log/slog的使用詳解

    官方提供的用于打印日志的包是標準庫中的 log 包,該包雖然被廣泛使用,但是缺點也很多,所以Go 1.21新增的 log/slog 完美解決了以上問題,下面我們就來看看log/slog包的使用吧
    2023-09-09
  • 詳解Go?sync?同步原語

    詳解Go?sync?同步原語

    Go?中不僅有?channel?這種?CSP?同步機制,還有?sync.Mutex、sync.WaitGroup?等比較原始的同步原語,使用它們,可以更靈活的控制數(shù)據(jù)同步和多協(xié)程并發(fā),這篇文章主要介紹了Go?sync?同步原語,需要的朋友可以參考下
    2023-12-12
  • go語言入門環(huán)境搭建及GoLand安裝教程詳解

    go語言入門環(huán)境搭建及GoLand安裝教程詳解

    這篇文章主要介紹了go語言入門環(huán)境搭建及GoLand安裝教程詳解,需要的朋友可以參考下
    2020-12-12
  • Go語言原子操作atomic的使用

    Go語言原子操作atomic的使用

    本文介紹了Go語言原子操作的使用方法,原子操作是一種無鎖的技術(shù),可通過CPU指令實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-10-10
  • go語言反射的基礎教程示例

    go語言反射的基礎教程示例

    這篇文章主要為大家介紹了go語言反射的基礎教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • omitempty在go中的使用方式

    omitempty在go中的使用方式

    在Go語言編程中,`omitempty`標記用于JSON編解碼過程中控制字段是否被包含,當結(jié)構(gòu)體字段標記為`omitempty`且字段值為空時,該字段不會出現(xiàn)在生成的JSON中,有助于優(yōu)化JSON結(jié)構(gòu)和減小數(shù)據(jù)體積,通過具體示例解釋了`omitempty`的工作機制和實際效果
    2024-09-09

最新評論