golang不到20行代碼實現路由調度

來源:互聯網
上載者:User

項目地址

github

本項目依賴

使用標準庫實現,無額外依賴

為什麼需要路由調度層

golang http標準庫只能精確匹配請求的URI,然後執行handler。現在一般web項目都至少有個Controller層,以struct實現,根據不同的請求路徑派發到不同的方法中去。

路由調度器定義

由於golang暫時還不可以動態建立對象(比如java的Class.forName("xxx").newInstance(),xxx是任意存在的class名稱)。所以需要手動註冊一下controller關係。

  1. 定義routes儲存controller指標
  2. 解析請求過來的URL查詢參數,暫訂aaction名稱,ccontroller名稱,本文偷了下懶,沒對PATH_INFO做處理,也沒有對actionName的首字母自動大寫,這個不影響本文要傳達的核心內容,有興趣的讀者可以自行實現。
  3. 根據URL中的controllerName找到對應的controller
  4. 使用反射將當前請求對象的*http.Requesthttp.ResponseWriter設定到該Controller
  5. 使用反射以及actionName對應該controller的方法
由於golang的繼承不是一般的OOP,所以也沒有父子類這種說法,路由註冊那裡只能使用interface{}

代碼實現

app/app.go

該檔案為核心調度檔案

package appimport (    "net/http"    "reflect"    "fmt")type application struct {    routes map[string]interface{}}func New() *application {    return &application{        routes: make(map[string]interface{}),    }}func (p *application) ServeHTTP(w http.ResponseWriter, r *http.Request) {    controllerName := r.URL.Query().Get("c")    actionName := r.URL.Query().Get("a")    if controllerName == "" || actionName == "" {        http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)        return    }    route, ok := p.routes[controllerName]    if !ok {        http.Error(w, "Controller Not Found", http.StatusNotFound)        return    }    ele := reflect.ValueOf(route).Elem()    ele.FieldByName("Request").Set(reflect.ValueOf(r))    ele.FieldByName("Response").Set(reflect.ValueOf(w))    ele.MethodByName(actionName).Call([]reflect.Value{})}func (p *application) printRoutes() {    for route, controller := range p.routes {        ele := reflect.ValueOf(controller).Type().String()        fmt.Printf("%s %s\n", route, ele)    }}func (p *application) Get(route string, controller interface{}) {    p.routes[route] = controller}func (p *application) Run(addr string) error {    p.printRoutes()    fmt.Printf("listen on %s\n", addr)    return http.ListenAndServe(addr, p)}

app/controller.go

控制器"基類"

package appimport "net/http"type Controller struct {    Response http.ResponseWriter    Request  *http.Request}

controller/site.go

具體商務邏輯類

package controllersimport (    "fmt"    "app")type SiteController struct {    app.Controller}func (p SiteController) Index() {    fmt.Fprint(p.Response, p.Request.RequestURI)}

main.go

入口檔案

package mainimport (    _ "github.com/go-sql-driver/mysql"    "app"    "controllers")func main() {    application := app.New()    application.Get("site", &controllers.SiteController{})    application.Run(":8080")}

運行項目

  1. 啟動進程
  2. 訪問http://localhost:8080?c=site&a=Index會輸出/?c=site&a=Index

寫在最後

希望這個小小的項目能啟發到各位讀者,早日開發出適合自己的Web架構!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.