使用Golang 封裝一個Api框架----請求處理篇


前言:此框架的請求處理主要是依賴於Golang中的net/http包

  1. http.ListenAndServe 方法的使用

    1. 實現http簡單服務示例:參考文檔 https://studygolang.com/pkgdoc

      1. 示例1

        http.Handle("/foo", fooHandler)
        http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
          fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
        })
        log.Fatal(http.ListenAndServe(":8080", nil))
        
      2. 示例2:

        s := &http.Server{
         Addr:           ":8080",
         Handler:        myHandler,
         ReadTimeout:    10 * time.Second,
         WriteTimeout:   10 * time.Second,
         MaxHeaderBytes: 1 << 20,
        }
        log.Fatal(s.ListenAndServe())
        
  2. 本框架的處理思路:

    1. 從http包看,http.ListenAndServe(":8080", nil) 這個方法的第二個參數是http.Handler對象,而這個對象是一個接口,所以要實現ServeHttp方法

      type Handler interface {
      	ServeHTTP(ResponseWriter, *Request)
      }
      
    2. 在core包下面聲明了一個Application對象,這個對象實現了 ServeHTTP 方法,在這個方法里面進行路由的判斷,然后根據取到的路由找到 控制器和對應的方法,最后在協程里面利用反射調用 對用的控制器的相應的方法從而得到調用方法的結果(這個結果指的是方法調用成功或者失敗之類的結果)。在執行調用方法的過程中,http請求的參數通過 ServeHTTP的 *Request對象獲取,http的響應的結果可以通過 fmt.Fprint(ResponseWriter對象, "響應結果字符串")。

      注:關於請求參數的獲取以及響應結果的返回,在之后的博客中會詳細講到。

    3. 框架入口:public包中的main.go

      func main() {
      	routers := route.GetRouter()
          controllers := route.GetControllers()
          app := new(core.Application)
          app.Routers = routers
          app.Controllers = controllers
          err := http.ListenAndServe("localhost:8080", app)
          if err != nil {
            log.Println("ListenAndServe: ", err)
          }
      	}
      }
      

      在這個方法中首先 初始化一個Application對象,然后獲取用戶注冊的路由及控制器,將其作為app對象的屬性賦給app對象,然后使用http.ListenAndServe("localhost:8080", app) 。當請求過來的時候就會直接到app的ServeHTTP方法中,然后就會順着 2 的思路執行。

  3. 其他處理

    1. 路由的處理

      在這個框架中路由如下:

      package route
      
      import "goweb/controller"
      
      var routers = map[string]string{
      	// 示例  請求類型@控制器@方法
      	"/test":   "get@TestController@Test",
      }
      
      var controllers = map[string]interface{}{
      	// 示例  反射中用到
      	"TestController": &controller.TestController{},
      }
      
      func GetRouter() map[string]string {
      	return routers
      }
      
      func GetControllers() map[string]interface{} {
      	return controllers
      }
      

      在1.2.3 中提到了這個框架的路由的使用時 賦值給app對象了,然后再app中進行路由處理。通過routers數組可以獲取路由和控制器、方法之間的關系,通過controllers數組獲取到對應的控制器的結構體的地址,然后通過反射機制調用對應的控制器的對應方法

    2. 利用反射調用方法

      // 反射調用方法     
      func CallFuncByName(myClass interface{}, funcName string, params ...interface{}) (out []reflect.Value, err error) {
      	myClassValue := reflect.ValueOf(myClass)
      	m := myClassValue.MethodByName(funcName)
      	if !m.IsValid() {
      		return make([]reflect.Value, 0), fmt.Errorf("Method not found \"%s\"", funcName)
      	}
      	in := make([]reflect.Value, len(params))
      	for i, param := range params {
      		in[i] = reflect.ValueOf(param)
      	}
      	out = m.Call(in)
      	return out, nil
      }
      

      反射一般用在知道對象及方法名稱,想要得到對象的類或者調用對象的方法的情況。在MVC框架中(根據解析到的路由,動態執行方法)用得比較多一些。

注:1. 本文涉及到的代碼的git倉庫地址:https://github.com/zhuchenglin/goweb
      2. 如需轉載請注明出處: https://www.cnblogs.com/zhuchenglin/p/12687746.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM