<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # Baa 路由 baa 基于 http resetfull 模式設計了路由管理器,提供了常規路由,參數路由,文件路由,靜態文件路由,還有組路由。 ## 常規路由 ``` func (b *Baa) Delete(pattern string, h ...HandlerFunc) RouteNode func (b *Baa) Get(pattern string, h ...HandlerFunc) RouteNode func (b *Baa) Head(pattern string, h ...HandlerFunc) RouteNode func (b *Baa) Options(pattern string, h ...HandlerFunc) RouteNode func (b *Baa) Patch(pattern string, h ...HandlerFunc) RouteNode func (b *Baa) Post(pattern string, h ...HandlerFunc) RouteNode func (b *Baa) Put(pattern string, h ...HandlerFunc) RouteNode ``` 接受兩個參數,一個是URI路徑,另一個是 [HandlerFunc](https://godoc.org/github.com/go-baa/baa#HandlerFunc) 類型,設定匹配到該路徑時執行的方法;允許多個,按照設定順序進行鏈式處理。 返回一個 [RouteNode](https://godoc.org/github.com/go-baa/baa#RouteNode),該Node只有一個方法,`Name(name string)` 用于命名該條路由規則,以備后用。 除了以上幾個標準方法,還支持多個method設定的路由姿勢: ``` func (b *Baa) Route(pattern, methods string, h ...HandlerFunc) RouteNode func (b *Baa) Any(pattern string, h ...HandlerFunc) RouteNode ``` ## 路由語法 ### 靜態路由 靜態路由語法就是沒有任何參數變量,pattern是一個固定的字符串。 使用示例: ``` package main import ( "gopkg.in/baa.v1" ) func main() { app := baa.New() app.Get("/foo", func(c *baa.Context) { c.String(200, c.URL(true)) }) app.Get("/bar", func(c *baa.Context) { c.String(200, c.URL(true)) }) app.Run("1323") } ``` 測試: ``` curl http://127.0.0.1:1323/foo curl http://127.0.0.1:1323/bar ``` ### 參數路由 靜態路由是最基礎的,但顯然滿足不了需求的,我們在程序中通常相同的資源訪問規則相同,不同的只是資源的編號,這時就該參數路由出場了。 > 參數路由以 `/` 為拆分單位,故每兩個斜線區間中只能有一個參數存在,更復雜的規則需要 正則路由。 參數路由以冒號 `:` 后面跟一個字符串作為參數名稱,可以通過 `Context`的 `Param` 系列方法獲取路由參數的值。 使用示例: ``` package main import ( "fmt" "gopkg.in/baa.v1" ) func main() { app := baa.New() app.Get("/user/:id", func(c *baa.Context) { c.String(200, "My user id is: " + c.Param("id")) }) app.Get("/user/:id/project/:pid", func(c *baa.Context) { id := c.ParamInt("id") pid := c.ParamInt("pid") c.String(200, fmt.Sprintf("user id: %d, project id: %d", id, pid)) }) app.Run("1323") } ``` 測試: ``` curl http://127.0.0.1:1323/user/101 curl http://127.0.0.1:1323/user/101/project/201 ``` ### 正則路由 `正則路由,默認的baa中不支持正則表達式路由,需要一個增強組件來支持。` 語法和參數路由接近,并兼容參數路由,可以直接使用 正則路由替換默認路由。 參數路由以冒號 `:` 后面跟一個字符串作為參數名稱,再加一對括號中間可以寫正則;如果省略括號默認為 `.*` 的正則匹配。 > 使用正則路由要先引入新的路由器,并通過DI替換掉內置路由。 使用示例: ``` package main import ( "fmt" "gopkg.in/baa.v1" "github.com/go-baa/router/regtree" ) func main() { app := baa.New() app.SetDI("router", regtree.New(app)) app.Get("/user/:id", func(c *baa.Context) { c.String(200, "My user id is: " + c.Param("id")) }) app.Get("/user/:id/project/:pid", func(c *baa.Context) { id := c.ParamInt("id") pid := c.ParamInt("pid") c.String(200, fmt.Sprintf("user id: %d, project id: %d", id, pid)) }) app.Get("/user-:id(\\d+)", func(c *baa.Context) { c.String(200, "My user id is: "+c.Param("id")) }) app.Get("/user-:id(\\d+)-project-:pid(\\d+)", func(c *baa.Context) { id := c.ParamInt("id") pid := c.ParamInt("pid") c.String(200, fmt.Sprintf("user id: %d, project id: %d", id, pid)) }) app.Run("1323") } ``` 測試: ``` curl http://127.0.0.1:1323/user/101 curl http://127.0.0.1:1323/user-101 curl http://127.0.0.1:1323/user/101/project/201 curl http://127.0.0.1:1323/user-101-project-201 ``` ## 路由選項 ``` func (b *Baa) SetAutoHead(v bool) ``` 我記得搜索引擎很喜歡用HEAD方法來檢查一個網頁是否能正常訪問。但我們一般又不會單獨寫一個HEAD的處理方法,一般行為是GET返回的數據不要內容。 使用 `app.SetAutoHead(true)` 將在設置 `GET` 方法時,自動添加 `HEAD` 路由,綁定和GET一樣的處理。 ``` func (b *Baa) SetAutoTrailingSlash(v bool) ``` 在URL訪問中,一個目錄要帶不帶最后的斜線也有很多爭議,google站長工具明確表示,帶不帶斜線將表示不同的URL資源,但是瀏覽習慣問題,很多時候帶不帶都能訪問到相同的資源目錄。 使用 `app.SetAutoTrailingSlash(true)` 將處理最后的斜線,將帶和不帶都統一行為,自動補全最后一個斜線。 ## 組路由 ``` func (b *Baa) Group(pattern string, f func(), h ...HandlerFunc) ``` 組路由,常常被同事問道,這個功能太好用了,你是怎么想到這樣的設計,我說,我抄的,我抄的 [macaron](https://github.com/go-macaron/macaron),就是這么`直白`。 組路由,顧名思義,用來處理一組路由的需求,可以設定統一的前綴,統一的前置方法。 使用示例: ``` package main import ( "fmt" "gopkg.in/baa.v1" ) func main() { app := baa.New() app.Group("/group", func() { app.Get("/", func(c *baa.Context) { c.String(200, "我是組的首頁") }) app.Group("/user", func() { app.Get("/", func(c *baa.Context) { c.String(200, "我是組的用戶") }) app.Get("/:id", func(c *baa.Context) { c.String(200, "in group, user id: "+c.Param("id")) }) }) app.Get("/:gid", func(c *baa.Context) { c.String(200, "in group, group id: "+c.Param("gid")) }) }, func(c *baa.Context) { // 我是組內的前置檢測,過不了我這關休想訪問組內的資源 }) app.Run("1323") } ``` 測試: ``` curl http://127.0.0.1:1323/group/ curl http://127.0.0.1:1323/group/user/ curl http://127.0.0.1:1323/group/user/101 curl http://127.0.0.1:1323/group/111 ``` ### 鏈式處理 一個URL請求可以先處理A,根據A的結果再執行B。 **舉個例子:** 一個URL要先判斷你登錄過才可以訪問,就可以設定兩個Handler,第一個 判斷是否登錄,如果沒登錄就調到登錄界面,否則繼續執行第二個真正的內容。 使用示例: ``` package main import ( "gopkg.in/baa.v1" ) func main() { app := baa.Default() app.Get("/", func(c *baa.Context) { c.String(200, "Hello, 世界") }) app.Post("/", func(c *baa.Context) { c.String(200, c.Req.Method) }) app.Get("/admin", func(c *baa.Context) { if c.GetCookie("login_id") != "admin" { c.Redirect(302, "/login") c.Break() } }, func(c *baa.Context) { c.String(200, "恭喜你,看到后臺了") }) app.Get("/login", func(c *baa.Context) { c.Resp.Header().Set("Content-Type", "text/html; charset=utf-8") c.SetCookie("login_id", "admin", 3600, "/") c.Resp.Write([]byte("登錄成功,<a href=\"/admin\">點擊進入后臺</a>")) }) app.Run(":1323") } ``` ## 命名路由 ``` func (n *Node) Name(name string) func (b *Baa) URLFor(name string, args ...interface{}) string ``` 前面可以看到添加路由后,返回了一個 `RouteNode` 說可以做命名路由,有什么用呢? 就是給一個URL起個名字,然后在程序中可以通過 `URLFor`方法來生成這個符合這個路由的URL路徑。 舉個栗子: ``` app := baa.New() app.Get("/user/:id/project", func(c *baa.Context) { c.String(200, c.Baa().URLFor("user_project", c.Param("id"))) }).Name("user_project") ``` 執行上面的方法,會輸出你當前訪問的URL,就是這個姿勢。 ## 文件路由 ``` func (b *Baa) Static(prefix string, dir string, index bool, h HandlerFunc) func (b *Baa) StaticFile(pattern string, path string) RouteNode ``` 在一個完整的應用中,我們除了業務邏輯,還有訪問圖片/CSS/JS等需求,通過文件路由,可以直接訪問文件或文件夾。 `app.StaticFile` 可以讓你直接訪問一個具體的文件,比如: robots.txt `app.Static` 可以訪問一個目錄下所有的資源,甚至列出目錄結構,類似文件服務器。 舉個例子: ``` app := baa.New() app.Static("/assets", "/data/www/public/asssets", true, func(c *baa.Context) { // 你可以對輸出的結果干點啥的 }) app.Static("/robots.txt", "/data/www/public/robots.txt") ``` 就是醬樣子,第一條路由就可以列出目錄和訪問下面的資源了。第二條路由可以直接返回一個靜態文件。 ## 自定義錯誤 ### 500錯誤 ``` func (b *Baa) SetError(h ErrorHandleFunc) ``` 要是運行過程中程序出錯了,怎么辦,會不會泄露你的隱私,能不能提供點錯誤日志? baa 默認在 `debug` 模式下向瀏覽器發送具體的錯誤信息,線上運行只顯示 `Internal Server Error` 并返回 `500` 錯誤頭。 可以通過 `app.SetError` 來設置錯誤處理方法,該方法接受一個 [ErrorHandleFunc](https://godoc.org/github.com/go-baa/baa#ErrorHandleFunc) 類型。 ### 404錯誤 ``` func (b *Baa) SetNotFound(h HandlerFunc) ``` baa默認返回 `Not Found` 和 `404` 錯誤頭,你也可以通過 `app.SetNotFound`來自定義錯誤處理,該方法接受一個 [HandlerFunc](https://godoc.org/github.com/go-baa/baa#HandlerFunc) 類型。 舉個栗子: ``` app := baa.New() app.SetError(func(err error, c *baa.Context) { c.Baa().Logger().Println("記錄日志", err) c.String(500, "出錯了") }) app.SetNotFound(func(c *baa.Context) { c.String(404, "頁面放假了,請稍后再來。") }) app.Run(":1323") ``` ## Websocket ``` func (b *Baa) Websocket(pattern string, h func(*websocket.Conn)) RouteNode ``` Websocket 用于和瀏覽器進行保持通話。 在這里我們嘗試了 官方的 `golang.org/x/net/websocket` 不好封裝,放棄了。 官方推薦了 `github.com/gorilla/websocket` 我們試了下,不錯哦,就用他了。 baa 的websocket路由,用于快速開始一個 websocket 服務,混合現有應用編程。 該方法有兩個參數,一個 `pattern` 路徑,一個 [*websocket.Conn]() 類型的鏈接。 舉個例子: ``` package main import ( "fmt" "time" "gopkg.in/baa.v1" "github.com/gorilla/websocket" ) func main() { app := baa.Default() app.Get("/", func(c *baa.Context) { c.String(200, "index") }) app.Websocket("/socket", func(ws *websocket.Conn) { for { fmt.Println("websocket retry read...") messageType, data, err := ws.ReadMessage() if err != nil { if websocket.IsCloseError(err) { app.Logger().Println("websocket ReadMessage error: connection is closed") } else { app.Logger().Println("websocket ReadMessage error:", err) } ws.Close() return } fmt.Println("websocket receive: ", messageType, string(data)) err = ws.WriteMessage(messageType, data) if err != nil { app.Logger().Println("websocket WriteMessage error:", err) ws.Close() return } } }) app.Run(":1234") fmt.Println("end") } ``` 含js和go代碼的完整示例:[example/websocket](https://github.com/go-baa/example/tree/master/websocket) websocket的具體使用請參考 [gorilla/websocket](http://godoc.org/github.com/gorilla/websocket)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看