main函數,實例化http server,自動加載路由映射表:api
package main import ( "go-safe-info-flow/controllers" "library" "runtime" ) func main() { //實例化一個HttpServer server := library.NewServer("", 8080) //業務使用的controller在這裏進行註冊,將c/a關係加入到路由映射表中以做自動路由 server.AddController(&controllers.FrontSkin{}) server.Run() }
library.HttpApi.go 路由規則的具體實現:mvc
package library import ( "net/http" "reflect" "runtime" "strconv" "strings" ) //http api最重要的兩部分 //1. 根據業務定製處理不一樣路由規則的handler 擴展到mvc結構中就是每個請求找到對應的m/c/a //2. 實例化一個server並 監聽端口 func NewServer(addr string, port int) *HttpServer { return &HttpServer{ httpAddr: addr, httpPort: port, mux: &httpMux{router: make(map[string]map[string]reflect.Type)}, } } //自定義一個server結構 type HttpServer struct { httpAddr string httpPort int mux *httpMux } //多路複用器 type httpMux struct { router map[string] /*controller*/ map[string] /*action*/ reflect.Type } const ( controllerSuffix = "Controller" actionSuffix = "Action" ) //添加controller func (this *HttpServer) AddController(c interface{}) { reflectType := reflect.TypeOf(c) // reflectVal := reflect.ValueOf(c) typeVal := reflectType.Elem() //獲取controller name 只有reflectType才能夠獲取 var controllerName string if hasSuffix := strings.HasSuffix(typeVal.Name(), controllerSuffix); hasSuffix { controllerName = strings.TrimSuffix(typeVal.Name(), controllerSuffix) } else { controllerName = strings.TrimSpace(typeVal.Name()) } //controller已經添加到路由中了 if _, ok := this.mux.router[controllerName]; ok { return } else { this.mux.router[controllerName] = make(map[string]reflect.Type) } this.mux.addAction(controllerName, reflectType) } func (this *httpMux) addAction(controllerName string, rt reflect.Type) { for i := 0; i < rt.NumMethod(); i++ { method := rt.Method(i).Name if strings.HasSuffix(method, actionSuffix) { action := strings.TrimSuffix(method, actionSuffix) this.router[controllerName][action] = rt.Elem() } } } //handler實現方法,自動路由,並執行相應的業務邏輯方法 func (this *httpMux) ServeHTTP(rw http.ResponseWriter, r *http.Request) { //解析參數 // r.ParseForm() path := strings.TrimPrefix(r.URL.Path, "/") if path == "" || path == "/" { // rw.WriteHeader(http.StatusForbidden) http.Error(rw, "forbidden", http.StatusForbidden) return } rPath := strings.Split(path, "/") cname := strings.Title(rPath[0]) if _, ok := this.router[cname]; ok { var mname string if len(rPath) == 1 || rPath[1] == "" { mname = "Index" } else { mname = strings.Title(rPath[1]) } if controller, ok := this.router[cname][mname]; ok { //初始化controller 返回指向struct的指針 //var in []reflect.Value vc := reflect.New(controller) methodName := mname + actionSuffix r.ParseForm() method := vc.MethodByName("Init") //初始化controller in := make([]reflect.Value, 0, 2) in = append(in, reflect.ValueOf(rw)) in = append(in, reflect.ValueOf(r)) method.Call(in) method = vc.MethodByName(methodName) method.Call([]reflect.Value{}) } else { http.NotFound(rw, r) return } } else { http.NotFound(rw, r) return } } //運行server func (server *HttpServer) Run() { runtime.GOMAXPROCS(runtime.NumCPU()) // addr := fmt.Sprintf("%s:%d", server.httpAddr, server.httpPort) addr := server.httpAddr + ":" + strconv.Itoa(server.httpPort) err := http.ListenAndServe(addr, server.mux) if err != nil { panic(err) } }