Routing in the Golang

Source: Internet
Author: User

Before there is an article more superficial analysis of the Golang server how to achieve, there is Handler , DefaultServeMux HandlerFunc the use of.

We now know that the DefaultServeMux pattern place to store and what handler we call it 路由 , then we may think, since we golang can achieve this 路由 , can we also imitate one?

First we need a container () that can hold the client's request 路由 .

Create a routing structure body

type CopyRouter struct {    router map[string]map[string]http.HandlerFunc}

Here we create a DefaultServeMux route like that.

Client requests are stored in a route

func (c *CopyRouter) HandleFunc(method, pattern string, handle http.HandlerFunc) {    if method == "" {        panic("Method can not be null!")    }    if pattern == "" {        panic("Pattern can not be null!")    }    if _, ok := c.router[method][pattern]; ok {        panic("Pattern Exists!")    }    if c.router == nil {        c.router = make(map[string]map[string]http.HandlerFunc)    }    if c.router[method] == nil {        c.router[method] = make(map[string]http.HandlerFunc)    }    c.router[method][pattern] = handle}

Here we imitate the source of ServeMux each of the URL corresponding to handler save.

Implementing the Handler interface

func (c *CopyRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {    if f, ok := c.router[r.Method][r.URL.String()]; ok {        f.ServeHTTP(w, r)    }}

Here's why we want to implement this handler interface, because we find that in the Listenandserve method, the final call h.ServeHTTP(w, r) , then we just need to let our definition of the route implementation Handler interface can be.

Get a route

func NewRouter() *CopyRouter {    return new(CopyRouter)}

Here, our own definition of the route is complete, let's look at how to use it.

func sayHi(w http.ResponseWriter, r *http.Request)  {    fmt.Fprint(w,"Hi")}func main() {    copyRouter := copyrouter.NewRouter()    copyRouter.HandleFunc("GET","/sayHi", sayHi)    log.Fatal(http.ListenAndServe("localhost:8080", copyRouter))}

This completes a high-imitation version of the custom route, is not and Golang provide us with a ServeMux very similar, of course, we this route is a low version, there are many details are not processed.

Now look again, our main function inside the code is not very beautiful, every time to write get or post method, then we can provide a more beautiful way? Yes, then let's wrap it up again.

func (c *CopyRouter) GET(pattern string, handler http.HandlerFunc){    c.HandleFunc("GET", pattern, handler)}func (c *CopyRouter) POST(pattern string, handler http.HandlerFunc){    c.HandleFunc("POST", pattern, handler)}...

Then modify the calling method.

copyRouter.GET("/sayHi",sayHi)

Does it look a lot more beautiful now? Yes, a lot of the web framework is the same, why it feels smooth to use, because these gods are standing in the perspective of our developers to consider the problem, provides a very convenient use of some, encapsulation is very perfect.

Think about what else we can do with this custom route, and if we want to record every access request, what should we do? Also very simple, we just need to write the logic in the ServeHTTP method, we can modify our code a little bit.

func (c *CopyRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {    if f, ok := c.router[r.Method][r.URL.String()]; ok {        func (handler http.Handler){            start := time.Now()            log.Printf(" 请求 [%s] 开始时间为 : %v\n", r.URL.String(), start)            f.ServeHTTP(w, r)            log.Printf(" 请求 [%s] 完成时间为 : %v\n", r.URL.String(), time.Since(start))        }(f)    }}

Here we have added a function to record the request time, so there are more things to do in this custom route.

Also, is it possible to change this type to handler when we define this routing structure? That map[string]map[string]http.HandlerFunc is, it is possible to modify this type map[string]map[string]http.Handler , but we need to make a change in the main method when we call it.

copyRouter.GET("/sayHi",HandlerFunc(sayHi))

Make a cast here, but this is not very beautiful.
See here, we should focus on a type in the source code, that is HandlerFunc .

type HandlerFunc func(ResponseWriter, *Request)func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {    f(w, r)}

Here HandlerFunc is the role of an adapter, this is a very clever design, I have to say that the golang interface is really very sophisticated design.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.