Пользовательский контроль маршрутизации Golang реализован (а)

Go

    Поскольку раньше я всегда был программистом на Java, на самом деле все полагаются на фреймворк в веб-разработке на Java, поэтому, когда я изучал Golang, я подумал о том, чтобы отказаться от фреймворка в разработке на Go и самому создать фреймворк для практики. Учась учиться на идеях Java и исходном коде некоторых фреймворков, он реализован на golang, чтобы одновременно достичь цели изучения Java и Golang, что очень красиво. Дизайн http в Golang очень легкий и хорошо масштабируемый.Новички могут легко создавать собственные функции маршрутизации, которые очень просты в использовании (здесь... Давайте поговорим о сервлетах Java, хотя я также прав, Java очень любит), см. демо ниже.

func HelloServer1(w http.ResponseWriter, req *http.Request) {

    fmt.Fprint(w,"hello world")
}
func main() {
    http.HandleFunc("/test", HelloServer1)
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err.Error())
    }
}скопировать код

     Всего несколькими строками кода вы можете успешно зарегистрировать интерфейс и запустить службу. Однако функции, предоставляемые собственным методом разработки, относительно упрощены.В настоящее время почти все реализации маршрутизации веб-приложений основаны на маршрутизаторе по умолчанию http, но маршрутизатор, поставляемый с Go, имеет несколько ограничений:

  • Установка параметров не поддерживается, например, сопоставление универсального типа, например /user/:uid.
  • Режим REST плохо поддерживается, и методы доступа не могут быть ограничены.Например, в приведенном выше примере пользователи, обращающиеся к /foo, могут использовать GET, POST, DELETE, HEAD и т. д. для доступа.
  • Слишком много правил роутинга для общих сайтов, и писать их громоздко, можно упростить методом struct.
        Go имеет такое ограничение, которое связано с методом по умолчанию, предоставляемым http.Давайте сначала рассмотрим две ключевые структуры http.
type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry
    hosts bool // whether any patterns contain hostnames
}

type muxEntry struct {
    explicit bool
    h        Handler
    pattern  string
}скопировать код

     Нам нужно сосредоточиться на двух ключевых местах, одно из них — это параметр m в ServeMux, его тип —map[string]muxEntry, тут естественно можно подумать, что параметр m отвечает за раздачу маршрутизации. Второй фокус — это muxEntry, muxEntry’sh HandlerСоответствующий интерфейс — это интерфейс, который мы написали, и вокруг этого интерфейса у http не так много других функций, даже нет единого стандарта веб-разработки, как в Java. Таким образом, http предоставляет только самые основные функции, и пользователям необходимо использовать эти функции в качестве основы, а затем YY может придумать структуру или более богатые функции, которые они хотят.
     Прежде всего, мы можем быстро и легко установить метод Http, чтобы в будущем поддерживать спецификацию URL RESTFUL. Есть два простых способа, первый способИспользование 2D-карты,Прямо сейчасmap[string]map[string]http.HandlerFunc, в котором одномерный ключ String представляет метод запроса, такой как post, get и т. д. Двумерная ключевая строка представляет URL-адрес, который необходимо сопоставить.Конечно, http.HandlerFunc — это особый метод обработки URL-запросов. Второй метод — это метод, принятый автором, фактически являющийся развитием первого метода. Тип метода фиксирован, фактически мы можем использовать массив, а значение равноmap[string]http.HandlerFuncреализовать.

const (
    GET         = iota
    POST
    PUT
    DELETE
    CONNECTIBNG
    HEAD
    OPTIONS
    PATCH
    TRACE
)скопировать код

     Ознакомившись с настройками вышеперечисленных констант, читатель уже должен знать, что я имею в виду,например: массив [0] представляет собой набор всех интерфейсов в рамках метода GET, а массив [1] представляет набор всех интерфейсов в рамках метода POST.Основной принцип на самом деле прост: все интерфейсы в методе Get сохраняются в значении array[0] для вывода других методов. Принцип прост, но дизайн фреймворка должен иметь высокую связность и низкую связанность.Распределение маршрутов в веб-фреймворке является основой, и на этом необходимо построить дополнительные функции, такие как фильтры. В начальном дизайне должна быть гарантирована масштабируемость, поэтому я думаю, что сложность заключается в этом. Код находится непосредственно ниже, и соответствующий код полностью прокомментирован.

package odserver

import (
    "net/http"
)
//实现IOdServer的接口,以及http提供ServeHttp方法
type OdServer struct {
    router MethodMaps
}


type IOdServer interface {
    GET(url string, f HandlerFunc)
    POST(url string, f HandlerFunc)
    PUT(url string, f HandlerFunc)
    DELETE(url string, f HandlerFunc)
}

type HandlerMapped struct {
    f HandlerFunc
}
//接口函数单位,即我们编写代码逻辑的函数
type HandlerFunc func(w http.ResponseWriter, req *http.Request)

func Default() *OdServer {
    return &OdServer{
        router:NewRouter(),
    }
}

//实现Handler接口,匹配方法以及路径
func (o *OdServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    //转发给doHandler进行执行
    o.doHandler(w,req)
}
//判断需要执行的Http Method,从而查找对应的接口并且执行
func (o *OdServer) doHandler(w http.ResponseWriter, req *http.Request) {
    switch req.Method {
    case http.MethodGet:
        {
            if hm, ok := o.router.GetMapping(req.URL.RequestURI()); ok {
                hm.f(w, req)
            }
        }
    case http.MethodPost:
        {
            if hm, ok := o.router.PostMapping(req.URL.RequestURI()); ok {
                hm.f(w, req)
            }

        }
    case http.MethodDelete:
        {
            if hm, ok := o.router.DeleteMapping(req.URL.String()); ok {
                hm.f(w, req)
            }
        }
    case http.MethodPut:
        {
            if hm, ok := o.router.PutMapping(req.URL.String()); ok {
                hm.f(w, req)
            }
        }
    default:
        {

        }
    }
}

func (o *OdServer) GET(url string, f HandlerFunc) {
    o.router.GetAdd(url, HandlerMapped{f: f})
}
func (o *OdServer) POST(url string, f HandlerFunc) {
    o.router.PostAdd(url, HandlerMapped{f: f})
}
func (o *OdServer) PUT(url string, f HandlerFunc) {
    o.router.PutAdd(url, HandlerMapped{f: f})
}
func (o *OdServer) DELETE(url string, f HandlerFunc) {
    o.router.DeleteAdd(url, HandlerMapped{f: f})
}
скопировать код
package odserver

/**
提供基本的路由功能,添加路由,查找路由
 */
const (
    GET         = iota
    POST
    PUT
    DELETE
    CONNECTIBNG
    HEAD
    OPTIONS
    PATCH
    TRACE
)

func NewRouter() MethodMaps {
    return []handler{
        GET:    make(handler),
        POST:   make(handler),
        PUT:    make(handler),
        DELETE: make(handler),
    }
}

type MethodMaps [] handler
type handler map[string]HandlerMapped
//映射路由,获取Get方法下对应的接口
func (m MethodMaps) GetMapping(url string) (HandlerMapped, bool) {
    if hm, ok := m[GET][url]; ok {
        return hm, true
    }
    return HandlerMapped{}, false
}
//映射路由,获取Post方法下对应的接口
func (m MethodMaps) PostMapping(url string) (HandlerMapped, bool) {
    if hm, ok := m[POST][url]; ok {
        return hm, true
    }
    return HandlerMapped{}, false
}
//映射路由,获取Delete方法下对应的接口
func (m MethodMaps) DeleteMapping(url string) (HandlerMapped, bool) {
    if hm, ok := m[DELETE][url]; ok {
        return hm, true
    }
    return HandlerMapped{}, false
}
//映射路由,获取Put方法下对应的接口
func (m MethodMaps) PutMapping(url string) (HandlerMapped, bool) {
    if hm, ok := m[PUT][url]; ok {
        return hm, true
    }
    return HandlerMapped{}, false
}
//增加Get方法下的接口
func (m MethodMaps) GetAdd(url string, mapped HandlerMapped) {
    if _, ok := m.GetMapping(url); ok {
        panic("duplicate url with get method")
    }
    m[GET].SetUrl(url,mapped)
}
//增加Post方法下的接口
func (m MethodMaps) PostAdd(url string, mapped HandlerMapped) {
    if _, ok := m.GetMapping(url); ok {
        panic("duplicate url with Post method")
    }
    m[POST].SetUrl(url,mapped)

}
//增加Put方法下的接口
func (m MethodMaps) PutAdd(url string, mapped HandlerMapped) {
    if _, ok := m.GetMapping(url); ok {
        panic("duplicate url with Put method")
    }
    m[PUT].SetUrl(url,mapped)

}
//增加Delete方法下的接口
func (m MethodMaps) DeleteAdd(url string, mapped HandlerMapped) {
    if _, ok := m.GetMapping(url); ok {
        panic("duplicate url with Delete method")
    }
    m[DELETE].SetUrl(url,mapped)
}
func (h handler) SetUrl(url string, mapped HandlerMapped) {
    h[url] = mapped
}скопировать код

     Как я уже сказал, я думаю, что более интересным для изучения Golang является то, что вы можете перенести то, что вы узнали из Java, и попытаться реализовать это в Golang, не только изучая Golang, но и улучшая свое понимание Java. Если у читателя есть лучший способ, пожалуйста, дайте мне знать
Ссылка: #Заметки об исследовании Golang — краткий анализ стандартной библиотеки «net/http» и самодельного простого фреймворка маршрутизации.