Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在net/http中注销处理程序?_Http_Go - Fatal编程技术网

如何在net/http中注销处理程序?

如何在net/http中注销处理程序?,http,go,Http,Go,我正在编写一个web服务器,其中需要在运行时注册处理程序。例如,“/create”将为所有URL(如“/123/*”等)创建一个新的处理程序。我需要一个对应的“/destroy/123”,它将注销“/123/*”的处理程序 以下是处理“/create”的代码 我尝试通过嵌入http.ServeMux来实现我自己的多路复用器,但它将其模式保存到私有变量中的处理程序映射(ServeMux.m)也许可以通过注册一个不返回任何内容(不向响应编写器写入任何内容)的处理程序来“完成”注销或者生成“未找到”类

我正在编写一个web服务器,其中需要在运行时注册处理程序。例如,“/create”将为所有URL(如“/123/*”等)创建一个新的处理程序。我需要一个对应的“/destroy/123”,它将注销“/123/*”的处理程序

以下是处理“/create”的代码


我尝试通过嵌入
http.ServeMux
来实现我自己的多路复用器,但它将其模式保存到私有变量中的处理程序映射(
ServeMux.m

也许可以通过注册一个不返回任何内容(不向响应编写器写入任何内容)的处理程序来“完成”注销或者生成“未找到”类型的响应。取决于您的要求和/或取消注册以前注册的处理程序的目的/效果。

我要做的是创建一个自定义的
ServerMux
。从
GOROOT/src/pkg/net/http/server.go
复制代码。它从837行开始,到939行结束

自定义ServerMux需要一种取消注册的方法。这应该很容易实现。只要抓住锁,然后
del()
地图条目。例如(所有未测试的代码):

为了使用这种新的多路复用器,您需要执行以下操作:

mux := newMux()
mux.Handle("/create", &factory)

srv := &http.Server {
    Addr: localhost:8080
    Handler: mux,
}
srv.ListenAndServe()

通过从另一个goroutine调用
deregister()
来修改mux是完全安全的,并且将修改
ListenAndServe()
路由消息的方式。

看起来您已经接受了答案,但我想提出一个替代解决方案

我怀疑是否需要添加一个定制的多路复用器。在本例中,我使用的是gorilla muxer,但这只是因为我熟悉它的模式匹配。理论上,您可以从传入URL匹配模式,而无需替换默认的muxer

我的代码在映射中维护处理程序函数(字符串:处理程序名称=>functionliteral)。。。这适用于使用默认的muxers HandleFunc方法

输入/输出示例:

获取/注册/123

获取/123
您好,来自123。

获取/销毁/123

获取/123
[无]

package main

import (
    "code.google.com/p/gorilla/mux"
    "flag"
    "log"
    "net/http"
)

// Wraps server muxer, dynamic map of handlers, and listen port.
type Server struct {
    Dispatcher *mux.Router
    Urls       map[string]func(w http.ResponseWriter, r *http.Request)
    Port       string
}

// May the signal never stop.
func main() {
    //Initialize Server
    server := &Server{Port: "3000", Dispatcher: mux.NewRouter(), Urls: make(map[string]func(w http.ResponseWriter, r *http.Request))}

    var port = flag.String("port", "3000", "Default: 3000; Set the port for the web-server to accept incoming requests")
    flag.Parse()

    server.Port = *port
    log.Printf("Starting server on port: %s \n", server.Port)

    server.InitDispatch()
    log.Printf("Initializing request routes...\n")

    server.Start() //Launch server; blocks goroutine.
}

func (s *Server) Start() {

    http.ListenAndServe(":"+s.Port, s.Dispatcher)
}

// Initialize Dispatcher's routes.
func (s *Server) InitDispatch() {
    d := s.Dispatcher

    // Add handler to server's map.
    d.HandleFunc("/register/{name}", func(w http.ResponseWriter, r *http.Request) {
        //somewhere somehow you create the handler to be used; i'll just make an echohandler
        vars := mux.Vars(r)
        name := vars["name"]

        s.AddFunction(w, r, name)
    }).Methods("GET")

    d.HandleFunc("/destroy/{name}", func(w http.ResponseWriter, r *http.Request) {
        vars := mux.Vars(r)
        name := vars["name"]
        s.Destroy(name)
    }).Methods("GET")

    d.HandleFunc("/{name}", func(w http.ResponseWriter, r *http.Request) {
        //Lookup handler in map and call it, proxying this writer and request
        vars := mux.Vars(r)
        name := vars["name"]

        s.ProxyCall(w, r, name)
    }).Methods("GET")
}

func (s *Server) Destroy(fName string) {
    s.Urls[fName] = nil //remove handler
}

func (s *Server) ProxyCall(w http.ResponseWriter, r *http.Request, fName string) {
    if s.Urls[fName] != nil {
        s.Urls[fName](w, r) //proxy the call
    }
}

func (s *Server) AddFunction(w http.ResponseWriter, r *http.Request, fName string) {
    f := func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("hello from" + fName))
    }

    s.Urls[fName] = f // Add the handler to our map
}

令人担忧的是,处理程序注册表将随着时间的推移而不断增长,并且由于处理程序查找的成本越来越高,从而导致请求周转速度的放缓。您的解决方案相当不错。如果基本URL结构解释是标准库的一部分,我可能会这样做。我的需求目前还不够复杂,无法引入一个新的包,但我怀疑它不需要太多的迭代就可以实现,那时我可能会选择Gorilla。
mux := newMux()
mux.Handle("/create", &factory)

srv := &http.Server {
    Addr: localhost:8080
    Handler: mux,
}
srv.ListenAndServe()
package main

import (
    "code.google.com/p/gorilla/mux"
    "flag"
    "log"
    "net/http"
)

// Wraps server muxer, dynamic map of handlers, and listen port.
type Server struct {
    Dispatcher *mux.Router
    Urls       map[string]func(w http.ResponseWriter, r *http.Request)
    Port       string
}

// May the signal never stop.
func main() {
    //Initialize Server
    server := &Server{Port: "3000", Dispatcher: mux.NewRouter(), Urls: make(map[string]func(w http.ResponseWriter, r *http.Request))}

    var port = flag.String("port", "3000", "Default: 3000; Set the port for the web-server to accept incoming requests")
    flag.Parse()

    server.Port = *port
    log.Printf("Starting server on port: %s \n", server.Port)

    server.InitDispatch()
    log.Printf("Initializing request routes...\n")

    server.Start() //Launch server; blocks goroutine.
}

func (s *Server) Start() {

    http.ListenAndServe(":"+s.Port, s.Dispatcher)
}

// Initialize Dispatcher's routes.
func (s *Server) InitDispatch() {
    d := s.Dispatcher

    // Add handler to server's map.
    d.HandleFunc("/register/{name}", func(w http.ResponseWriter, r *http.Request) {
        //somewhere somehow you create the handler to be used; i'll just make an echohandler
        vars := mux.Vars(r)
        name := vars["name"]

        s.AddFunction(w, r, name)
    }).Methods("GET")

    d.HandleFunc("/destroy/{name}", func(w http.ResponseWriter, r *http.Request) {
        vars := mux.Vars(r)
        name := vars["name"]
        s.Destroy(name)
    }).Methods("GET")

    d.HandleFunc("/{name}", func(w http.ResponseWriter, r *http.Request) {
        //Lookup handler in map and call it, proxying this writer and request
        vars := mux.Vars(r)
        name := vars["name"]

        s.ProxyCall(w, r, name)
    }).Methods("GET")
}

func (s *Server) Destroy(fName string) {
    s.Urls[fName] = nil //remove handler
}

func (s *Server) ProxyCall(w http.ResponseWriter, r *http.Request, fName string) {
    if s.Urls[fName] != nil {
        s.Urls[fName](w, r) //proxy the call
    }
}

func (s *Server) AddFunction(w http.ResponseWriter, r *http.Request, fName string) {
    f := func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("hello from" + fName))
    }

    s.Urls[fName] = f // Add the handler to our map
}