我正在编写一个Web服务器,其中需要在运行时注册处理程序。例如,“ / create”将为所有URL(例如“ / 123 / ”等)创建一个新的处理程序。我需要一个相应的“ / destroy / 123”,它将为“ / 123 / ”注销处理程序。
这是用于处理“ / create”的代码
package main import ( "fmt" "net/http" ) type MyHandler struct { id int } func (hf *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, r.URL.Path) } // Creates MyHandler instances and registers them as handlers at runtime type HandlerFactory struct { handler_id int } func (hf *HandlerFactory) ServeHTTP(w http.ResponseWriter, r *http.Request) { hf.handler_id++ handler := MyHandler{hf.handler_id} handle := fmt.Sprintf("/%d/", hf.handler_id) http.Handle(handle, &handler) } func main() { factory := HandlerFactory{0} http.Handle("/create", &factory) http.ListenAndServe("localhost:8080", nil) }
我尝试通过嵌入来实现自己的多路复用器,http.ServeMux但它在私有变量(ServeMux.m)中保留了其模式到处理程序的映射
http.ServeMux
ServeMux.m
我要做的是创建一个自定义ServerMux。复制中的代码GOROOT/src/pkg/net/http/server.go。它始于837行,结束于939。
ServerMux
GOROOT/src/pkg/net/http/server.go
自定义ServerMux将需要一种注销方法。这应该易于实现。只需抓住锁和del()地图条目即可。例如(所有代码未经测试):
del()
// TODO: check if registered and return error if not. // TODO: possibly remove the automatic permanent link between /dir and /dir/. func (mux *MyMux) Deregister(pattern string) error { mux.mu.Lock() defer mux.mu.Unlock() del(mux.m, pattern) return nil }
为了使用这个新的多路复用器,您需要执行以下操作:
mux := newMux() mux.Handle("/create", &factory) srv := &http.Server { Addr: localhost:8080 Handler: mux, } srv.ListenAndServe()
通过deregister()从另一个goroutine 调用来修改多路复用器是完全安全的,并且将修改ListenAndServe()路由消息的方式。
deregister()
ListenAndServe()