golang实现路由
更新时间:2023-12-19第一段:路由介绍
在web开发中,路由负责分发请求到对应的处理器(handler)函数,是实现网站控制器的重要组成部分。
一个请求(request)通常由一个HTTP方法(GET、POST、PUT、DELETE等)和一个路径(path)组成,在路由中,我们需要匹配请求的方法和路径,然后执行对应的处理器函数。
下面我们将用golang实现一种简单而可靠的路由。
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", indexHandler)
http.HandleFunc("/hello", helloHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, Go!")
}
第二段:路由实现步骤
实现一个路由需要分为两个步骤:路由注册和路由匹配Handlers。
路由注册是指将一组固定的HTTP路由和处理器函数建立映射关系的过程。对于每一个HTTP路由和处理器函数的映射,我们通常使用两种方式来定义它们:
- 使用HandleFunc函数注册路由和handler:
- 使用Handle函数注册路由和handler:
http.HandleFunc("/", indexHandler)
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
路由匹配是指当接收到请求后,根据请求的路径确定对应的处理器函数的过程。我们可以通过如下方式来匹配路由:
- 使用mux.NewRouter()方法创建一个路由对象:
- 使用.Handle()方法或.HandleFunc()方法向路由对象注册处理器:
- 使用http.ListenAndServe()方法将路由对象监听在本地的8080端口:
import "github.com/gorilla/mux"
router := mux.NewRouter()
// 处理"/"路径的请求
router.HandleFunc("/", homeHandler)
// 处理"/products"路径下的GET请求
router.HandleFunc("/products", productsHandler).Methods("GET")
http.ListenAndServe(":8080", router)
第三段:路由参数
在匹配路由时,有时需要从URL中获取参数,如RESTful API的URI中包含了参数。在golang中,我们可以使用"github.com/gorilla/mux"包获取URL中的参数。
下面我们演示如何从URL中获取参数,并将参数传入处理器函数:
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
}
func ArticleHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
category := vars["category"]
id := vars["id"]
fmt.Fprintf(w, "You've requested the article on category:%s and id:%s\n", category, id)
}
第四段:路由过滤器
在路由处理时,有些情况下,需要对一些请求做一些比较特殊的处理,比如:请求需要鉴权、请求需要浏览器支持Cookie等。这时候,就需要在路由处理之前加入一个中间件,即过滤器,来过滤这些请求。
下面我们演示如何使用壳子函数来构建过滤器来校验请求是否是从白名单中发起的:
func middleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 检查header属性并通过或拒绝请求
if check(r) {
h.ServeHTTP(w, r) // 通过
} else {
http.Error(w, "Forbidden", http.StatusForbidden) // 拒绝
}
})
}
func main() {
http.HandleFunc("/index", indexHandler)
http.HandleFunc("/about", aboutHandler)
// 使用空洞函数中间件进行过滤
filter := middleware(http.DefaultServeMux)
http.ListenAndServe(":8080", filter)
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to my website!")
}
func aboutHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "About us")
}
在上面例子中,我们使用了带有壳子函数的中间件经过检查才能继续执行请求处理。