Golang Http.handler Interface 1. Standard library Interface Definition
Package HTTP
Type Handler interface {
servehttp (w responsewriter, R *request)
}
func Listenandserve ( Address string, h Handler) error
The Listenandserve function requires a server address such as "localhost:8000", and a handler interface instance that handles all requests. It will run until the service fails (or fails to start) because of an error, and its return value must be a non-empty error.
2. Small demo
The type dollars float32 func (d dollars) string () string {return FMT. Sprintf ("$%.2f", D)} type MyHandler map[string]dollars func (self MyHandler) servehttp (w http. Responsewriter, req *http. Request) {switch req. Url. Path {case '/list ': for item, Price: = Range Self {fmt. fprintf (W, "%s:%s\n", Item, Price)} case "/price": Item: = req. Url. Query (). Get (' item ') Price, OK: = Self[item] If!ok {w.writeheader http. Statusnotfound)//404 FMT. fprintf (W, "No such item:%q\n", item) return} FMT. fprintf (W, "%s\n", Price) Default:w.writeheader (http. Statusnotfound)//404 FMT. fprintf (W, "No such page:%s\n", req. URL)} func main () {handler: = myhandler{"shoes": $, "Socks": 5} log. Fatal (http. Listenandserve ("localhost:8000", Handler))}
Now handler is based on the path part of the URL (Req.URL.Path) to decide what logic to perform. If this handler does not recognize the path, it will call the W. Writeheader (http. Statusnotfound) returns a HTTP404 error for the client
$ Curl Http://localhost:8000/list
shoes: $50.00
Socks: $5.00
$ curl http://localhost:8000/price?item= Socks
$5.00
$ curl http://localhost:8000/price?item=shoes
$50.00
$ curl Http://localhost:8000/ Price?item=hat
No such item: "Hat"
$ curl http://localhost:8000/help
No such page:/help
Obviously we can continue to add a case to the Servehttp method, but in a practical application it would be useful to define the logic in each case to a separate method or function. For more complex applications, a servemux gathers a batch of Http.handler into a single http.handler, which is combined to handle more complex routing requirements.
3.servemux.handle Improved version
Type MyHandler map[string]dollars
func (self MyHandler) List (w http. Responsewriter, req *http. Request {
for item, Price: = Range Self {
fmt. fprintf (W, "%s:%s\n", item, Price)
}
}
func (self MyHandler) Price (w http. Responsewriter, req *http. Request) {
Item: = req. Url. Query (). Get (' item ') Price
, OK: = Self[item]
if!ok {
W.writeheader http. Statusnotfound)//404
fmt. fprintf (W, "No such item:%q\n", item)
return
}
fmt. fprintf (W, "%s\n", Price)
}
func main () {
handler: = myhandler{"shoes": $, "Socks": 5}
MUX: = http. Newservemux ()
mux. Handle ("/list", http. Handlerfunc (handler.list))
Mux. Handle ("/price", http. Handlerfunc (handler.price))
log. Fatal (http. Listenandserve ("localhost:8000", MUX)
}
Statement http. Handlerfunc (handler.list) is a conversion rather than a function call, because HTTP. Handlerfunc is a type. It has the following definition:
Package HTTP
Type Handlerfunc func (w responsewriter, R *request)
func (f Handlerfunc) servehttp (w responsewriter , R *request) {
f (W, R)
}
Handlerfunc shows some unusual features in the go Language interface mechanism. This is an interface that has implemented HTTP. The function type of the handler method. The behavior of the Servehttp method invokes its own function. So Handlerfunc is an adapter that lets the function value meet an interface (here is HTTP.) The handler interface adapter, because the Servehttp method is implemented, has the same function signature as the only method of this interface. In fact, this technique allows a single type such as MyHandler to satisfy the Http.handler interface in a variety of ways: a list method through it, a price method through it, and so on.
4.servemux.handlefunc Improved version
Because Servemux.handle registration is very common in paragraph 3, Servemux has a convenient Handlefunc method (Servemux.handle), which helps us simplify the handler registration code in this way:
Mux. Handlefunc ("/list", handler.list)
mux. Handlefunc ("/price", Handler.price)
So for convenience, the Net/http package provides a global Servemux instance Defaultservermux and packet-level http.handle and Http.handlefunc functions. Now, in order to use Defaultservemux as the main handler of the server, we do not need to pass it to the Listenandserve function; nil value can work.
Func Main () {
handler: = myhandler{"shoes": $, "Socks": 5}
http. Handlefunc ("/list", handler.list)
http. Handlefunc ("/price", Handler.price)
log. Fatal (http. Listenandserve ("localhost:8000", nil)
}
The code differs from paragraph 3 by not manually creating the Servemux instance, but by using the Defaultservermux Global instance of the Net/http package.
MORE:
Based on concurrency considerations, the Web server should call each handler in a new coprocessor, so be sure to use preventative measures such as locking mechanisms when handler obtains other threads or variables that can be accessed by other requests in the handler itself.
This article is derived from the Go Language Bible Chapter 7.7. http. Handler interface