最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang第三方庫mux的實現(xiàn)

 更新時間:2025年06月09日 09:29:28   作者:JustGopher  
Gorilla/mux 是 Go 語言中功能更全面的路由庫,支持參數(shù)匹配、正則、中間件、子路由分組等,本文主要介紹了golang第三方庫mux的實現(xiàn),感興趣的可以了解一下

gorilla/mux

一:golang自帶路由介紹

golang 自帶路由庫 http.ServerMux ,實際上是一個 map[string][Handler],是請求的url路徑和該url路徑對于的一個處理函數(shù)的映射關(guān)系。這個實現(xiàn)比較簡單,有一些缺點:

  • 不支持參數(shù)設(shè)定,例如 /user/:uid 這種泛型類型匹配
  • 無法很友好的支持REST模式,無法限制訪問方法(POST,GET等)
  • 也不支持正則

二:gorilla/mux路由

GitHub 地址:https://github.com/gorilla/mux

上面所指出來的glang自帶路由的缺點,gorilla/mux 都具備,而且還兼容 http.ServerMux。除了支持路徑正則,命名路由,還支持中間件等等功能。所以mux是一個短小精悍,功能很全的路由。

1. 普通路由

示例 demo1.go

package main
 
import (
	"fmt"
	"github.com/gorilla/mux"
	"net/http"
)
 
func main() {
	r := mux.NewRouter()
	//普通路由
	r.HandleFunc("/", IndexHandler)
	r.HandleFunc("/products", ProductsHandler)
 
	http.ListenAndServe(":8080", r)
}
 
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, "hello world")
}
 
func ProductsHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, "hello, Products")
}

上面mux的普通路由是不是似曾相識,跟golang標準庫用法一樣

在瀏覽器訪問:http://localhost:8080/products
輸出:hello, Products

2. 參數(shù)路由

參數(shù)路由,可以是普通路由,還可以是正則匹配
示例 demo2.go:

package main
 
import (
	"net/http"
 
	"fmt"
 
	"github.com/gorilla/mux"
)
 
//路由參數(shù)
func main() {
	r := mux.NewRouter()
	//1. 普通路由參數(shù)
	// r.HandleFunc("/articles/{title}", TitleHandler)
 
	//2. 正則路由參數(shù),下面例子中限制為英文字母
	r.HandleFunc("/articles/{title:[a-z]+}", TitleHandler)
 
	http.ListenAndServe(":8080", r)
}
 
//https://github.com/gorilla/mux#examples
func TitleHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r) // 獲取參數(shù)
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, "title: %v\n", vars["title"])
}

第1個普通路由參數(shù),就是啥參數(shù)都可以,不管是字母,數(shù)字,還是中文等
第2個正則路由參數(shù),限制了只能是英文字母,否則會報 404 page not found

3. 路由匹配 Matching Routes

https://github.com/gorilla/mux#matching-routes
我們也可以限制路由或者子路由。

3.1 匹配host

r := mux.NewRouter()
//只匹配 www.example.com
r.Host("www.example.com")
// 動態(tài)匹配子路由
r.Host("{subdomain:[a-z]+}.example.com")

3.2 更多的一些其他匹配

見下面的更多匹配的例子:

r := mux.NewRouter()
 
r.PathPrefix("/products/")    //前綴匹配
r.Methods("GET", "POST")      //請求方法匹配
r.Schemes("https")            //schemes
r.Headers("X-Requested-With", "XMLHttpRequest")  //header 匹配
r.Queries("key", "value")  //query的值匹配
 
// 用戶自定義方法 匹配
r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { 
    return r.ProtoMajor == 0
})

把上面的聯(lián)合起來在一個單獨的route里

r.HandleFunc("/products", ProductsHandler).
  Host("www.example.com").
  Methods("GET").
  Schemes("http")	

3.3 子路由匹配

Subrouter() 可以設(shè)置子路由

r := mux.NewRouter()
s := r.Host("www.example.com").Subrouter()
 
s.HandleFunc("/products/", ProductsHandler)
s.HandleFunc("/products/{key}", ProductHandler)
s.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)

3.4 多個路由匹的順序

如果有多個路由添加到路由器里面,那么匹配順序是怎么樣?按照添加的先后順序匹配。比如有2個路由都匹配了,那么優(yōu)先匹配第一個路由。

r := mux.NewRouter()
r.HandleFunc("/specific", specificHandler)
r.PathPrefix("/").Handler(catchAllHandler)

4. 設(shè)置路由前綴

PathPrefix() 設(shè)置路由前綴

r := mux.NewRouter()
 
//PathPrefix() 可以設(shè)置路由前綴
product := r.PathPrefix("/products").HandleFunc("/", ProductsHandler)

路由前綴一般情況下不會單獨使用,而是和子路由結(jié)合起來用,實現(xiàn)路由分組

5. 分組路由

可以根據(jù)前面的子路由和路由前綴的功能,綜合運用就可以設(shè)置分組路由了
實例:grouprouter.go

package main
 
import (
	"fmt"
	"github.com/gorilla/mux"
	"net/http"
)
 
//子路由, 分組路由
func main() {
	r := mux.NewRouter()
 
	//PathPrefix() 可以設(shè)置路由前綴,設(shè)置路由前綴為products
	products := r.PathPrefix("/products").Subrouter()
	//"http://localhost:8080/products/", 最后面的斜線一定要,不然路由不正確,頁面出現(xiàn)404
	products.HandleFunc("/", ProductsHandler)
	//"http://localhost:8080/products/{key}"
	products.HandleFunc("/{key}", ProductHandler)
 
	users := r.PathPrefix("/users").Subrouter()
	// "/users"
	users.HandleFunc("/", UsersHandler)
	// "/users/id/參數(shù)/name/參數(shù)"
	users.HandleFunc("/id/{id}/name/{name}", UserHandler)
 
	http.ListenAndServe(":8080", r)
}
 
func ProductsHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, "%s", "products")
}
 
func ProductHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r) //獲取路由的值
	fmt.Fprintf(w, "key: %s", vars["key"])
}
 
func UsersHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, " %s \r\n", "users handler")
}
 
func UserHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r) //獲取值
	id := vars["id"]
	name := vars["name"]
	fmt.Fprintf(w, "id: %s, name: %s \r\n", id, name)
}

6. 路由中間件

https://github.com/gorilla/mux#middleware
Mux middlewares are defined using the de facto standard type: 在mux中路由中間件的定義

type MiddlewareFunc func(http.Handler) http.Handler

示例1:middleware1.go

package main
 
import (
	"fmt"
	"net/http"
 
	"github.com/gorilla/mux"
)
 
func main() {
	r := mux.NewRouter()
	r.HandleFunc("/", handler)
 
	r.Use(loggingMiddleware)
 
	http.ListenAndServe(":8080", r)
}
 
func loggingMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		//Do stuff here
		fmt.Println(r.RequestURI)
		fmt.Fprintf(w, "%s\r\n", r.URL)
		// Call the next handler, which can be another middleware in the chain, or the final handler.
		next.ServeHTTP(w, r)
	})
}
 
func handler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("handle middleware"))
	fmt.Println("print handler")
}

示例2:middleware2.go

在來看一個復雜點的例子:

package main
 
import (
	"fmt"
	"net/http"
	"strings"
 
	"github.com/gorilla/mux"
)
 
type authMiddleware struct {
	tokenUsers map[string]string
}
 
func (amw *authMiddleware) Populate() {
	amw.tokenUsers = make(map[string]string)
	amw.tokenUsers["000"] = "user0"
	amw.tokenUsers["aaa"] = "userA"
	amw.tokenUsers["05ft"] = "randomUser"
	amw.tokenUsers["deadbeef"] = "user0"
}
 
func (amw *authMiddleware) Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		token := strings.Trim(r.Header.Get("X-Session-Token"), " ")
		if token == "" {
			fmt.Fprintf(w, "token is error \r\n")
		}
 
		if user, found := amw.tokenUsers[token]; found {
			//we found the token in out map
			fmt.Printf("Authenticated user: %s\n", user)
			fmt.Fprintf(w, "Authenticated user: %s\n", user)
			// Pass down the request to the next middleware (or final handler)
			next.ServeHTTP(w, r)
		} else {
			// Write an error and stop the handler chain
			http.Error(w, "Forbidden", http.StatusForbidden)
		}
	})
}
 
func main() {
	r := mux.NewRouter()
	r.HandleFunc("/", handler)
 
	amw := authMiddleware{}
	amw.Populate()
 
	r.Use(amw.Middleware)
 
	http.ListenAndServe(":8080", r)
}
 
func handler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("handler"))
}

用 insomnia 軟件測試,如下圖

在這里插入圖片描述

X-Session-Token=aaa 返回時正確

那 -Session-Token=aaaa 呢

在這里插入圖片描述

返回 403 了

7. Walking Routes 遍歷注冊的所有路由

package main
 
import (
	"fmt"
	"net/http"
	"strings"
 
	"github.com/gorilla/mux"
)
 
func handler(w http.ResponseWriter, r *http.Request) {
	return
}
 
//https://github.com/gorilla/mux#walking-routes
func main() {
	r := mux.NewRouter()
	r.HandleFunc("/", handler)
	r.HandleFunc("/products", handler).Methods("POST")
	r.HandleFunc("/articles", handler).Methods("GET")
	r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
	r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
	err := r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
		pathTemplate, err := route.GetPathTemplate()
		if err == nil {
			fmt.Println("ROUTE:", pathTemplate)
		}
		pathRegexp, err := route.GetPathRegexp()
		if err == nil {
			fmt.Println("Path regexp:", pathRegexp)
		}
		queriesTemplates, err := route.GetQueriesTemplates()
		if err == nil {
			fmt.Println("Queries templates:", strings.Join(queriesTemplates, ","))
		}
		queriesRegexps, err := route.GetQueriesRegexp()
		if err == nil {
			fmt.Println("Queries regexps:", strings.Join(queriesRegexps, ","))
		}
		methods, err := route.GetMethods()
		if err == nil {
			fmt.Println("Methods:", strings.Join(methods, ","))
		}
		fmt.Println()
		return nil
	})
 
	if err != nil {
		fmt.Println(err)
	}
 
	http.Handle("/", r)
	http.ListenAndServe(":8080", nil)
}

8. 其他示例

請求方法限制

demo3.go:

package main
 
import (
	"fmt"
	"github.com/gorilla/mux"
	"net/http"
)
 
// 請求方法的限制, Methods()
func main() {
	r := mux.NewRouter()
 
	r.HandleFunc("/products", ProductsHandler).Methods("GET", "POST")
 
	r.Handle("/products/{id}", &ProductsIdHandler{}).Methods("GET")
	http.ListenAndServe(":8080", r)
}
 
func ProductsHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, "hello, products! ")
}
 
type ProductsIdHandler struct{}
 
func (handler *ProductsIdHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, "products id: %s", vars["id"])
}

請求頭限制

在路由定義中可以通過Headers() 方法來限制設(shè)置請求頭的匹配。
demo4.go

package main
 
import (
	"fmt"
	"net/http"
 
	"github.com/gorilla/mux"
)
 
// 請求頭的限制,用Headers() 來限制
func main() {
	r := mux.NewRouter()
 
	r.HandleFunc("/products", func(w http.ResponseWriter, r *http.Request) {
		header := "Request-Limit-Test"
		fmt.Fprintf(w, "contain headers: %s = %s \n", header, r.Header[header])
	}).Headers("Request-Limit-Test", "RequestLimitTest").Methods("POST")
 
	http.ListenAndServe(":8080", r)
}

自定義匹配規(guī)

用 MatcherFunc() 來自定義規(guī)則
示例 demo5.go:**

package main
 
import (
	"fmt"
	"net/http"
 
	"github.com/gorilla/mux"
)
 
//自定義匹配 MatcherFunc()
func main() {
	r := mux.NewRouter()
 
	r.HandleFunc("/products/matcher", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "FormValue: %s ", r.FormValue("func"))
	}).MatcherFunc(func(req *http.Request, match *mux.RouteMatch) bool {
		b := false
		if req.FormValue("func") == "matcherfunc" {
			b = true
		}
		return b
	})
 
	http.ListenAndServe(":8080", r)
}
在瀏覽器中:http://127.0.0.1:8080/products/matcher?func=matcherfunc
輸出:FormValue: matcherfunc 

命名路由 Registered URLs

namerouter.go

package main
 
import (
	"fmt"
	"github.com/gorilla/mux"
	// "log"
	"net/http"
)
 
// 命名路由 Name(), 獲取路由URL, URL()
func main() {
	r := mux.NewRouter()
	r.HandleFunc("/products/{category}/{id:[0-9]+}", ProductHandler).Name("product")
 
	//獲取路由的URL
	url1, err := r.Get("product").URL()
	fmt.Println(err) //error: mux: number of parameters must be multiple of 2, got [/]
	if err == nil {
		fmt.Println("get URL: \r\n", url1)
	}
 
	//獲取路由的url后,也可以拼裝你需要的URL
	url2, err := r.Get("product").URL("category", "tech", "id", "13")
	if err == nil {
		fmt.Println("new url: ", url2) //new url:  /products/tech/13
	}
 
	http.ListenAndServe(":8080", r)
}
 
func ProductHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	vars := mux.Vars(r)
 
	fmt.Fprintf(w, "url: %s, category: %s, id: %s", r.URL, vars["category"], vars["id"])
	//瀏覽器: http://localhost:8080/products/id/23
 
	//output
	//url: /products/id/23, category: id, id: 23
}

根據(jù)命名的路由來獲取路由URL r.Get(“product”).URL()

到此這篇關(guān)于golang第三方庫mux的實現(xiàn)的文章就介紹到這了,更多相關(guān)golang mux內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang實現(xiàn)Redis過期時間實例探究

    Golang實現(xiàn)Redis過期時間實例探究

    這篇文章主要介紹了Golang實現(xiàn)Redis過期時間實例探究,
    2024-01-01
  • Golang?json?庫中的RawMessage功能原理

    Golang?json?庫中的RawMessage功能原理

    今天我們來學習一個 Golang 官方 json 庫提供了一個經(jīng)典能力RawMessage,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • golang字符串拼接實現(xiàn)方式和區(qū)別對比

    golang字符串拼接實現(xiàn)方式和區(qū)別對比

    本文介紹了Go語言中字符串拼接的多種方法及其優(yōu)缺點,推薦使用strings.Builder進行頻繁拼接以優(yōu)化內(nèi)存分配和性能,同時,還討論了通過sync.Pool優(yōu)化高頻創(chuàng)建的對象,以減少垃圾回收壓力,感興趣的朋友一起看看吧
    2025-02-02
  • Go如何實現(xiàn)Websocket服務(wù)以及代理

    Go如何實現(xiàn)Websocket服務(wù)以及代理

    這篇文章主要介紹了Go如何實現(xiàn)Websocket服務(wù)以及代理方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Golang實現(xiàn)自己的orm框架實例探索

    Golang實現(xiàn)自己的orm框架實例探索

    這篇文章主要為大家介紹了Golang實現(xiàn)自己的orm框架實例探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • Go語言Gin框架中使用MySQL數(shù)據(jù)庫的三種方式

    Go語言Gin框架中使用MySQL數(shù)據(jù)庫的三種方式

    本文主要介紹了Go語言Gin框架中使用MySQL數(shù)據(jù)庫的三種方式,通過三種方式實現(xiàn)增刪改查的操作,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • Go語言中常用的基礎(chǔ)方法總結(jié)

    Go語言中常用的基礎(chǔ)方法總結(jié)

    這篇文章主要為大家詳細介紹了Go語言中常用的一些基礎(chǔ)方法,例如:使用正則表達式驗證字符串、格式化字符串、時間的比較等等,需要的可以參考一下
    2022-09-09
  • go語言通過管道連接兩個命令行進程的方法

    go語言通過管道連接兩個命令行進程的方法

    這篇文章主要介紹了go語言通過管道連接兩個命令行進程的方法,實例分析了Go語言操作命令行進程的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-03-03
  • 詳解Go channel管道的運行原理

    詳解Go channel管道的運行原理

    Go推薦通過通信來共享內(nèi)存,而channel就實現(xiàn)了這一理念。那channel是怎么運行的呢?本文將帶你搞懂Go channel管道的運行原理,感興趣的同學可以參考一下
    2023-05-05
  • Golang優(yōu)雅保持main函數(shù)不退出的辦法

    Golang優(yōu)雅保持main函數(shù)不退出的辦法

    很多時候我們需要讓main函數(shù)不退出,讓它在后臺一直執(zhí)行,下面這篇文章主要給大家介紹了關(guān)于Golang優(yōu)雅保持main函數(shù)不退出的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-07-07

最新評論

民权县| 泌阳县| 天气| 保山市| 泸溪县| 许昌市| 新巴尔虎右旗| 富宁县| 漳平市| 正安县| 航空| 开化县| 禹州市| 大邑县| 涞源县| 新巴尔虎右旗| 富顺县| 咸宁市| 安图县| 永宁县| 象州县| 菏泽市| 交口县| 酉阳| 九龙县| 万荣县| 拉孜县| 辉县市| 柳林县| 綦江县| 依兰县| 华蓥市| 阿拉尔市| 平武县| 囊谦县| 全南县| 阜城县| 泸州市| 司法| 龙口市| 定日县|