From 0f4501c696c4e28a8c1440fbb052c307265cdda5 Mon Sep 17 00:00:00 2001 From: Anchor Date: Tue, 9 Sep 2014 23:14:34 -0700 Subject: [PATCH] Edited 03.4.md for grammar, typos and improved clarity --- en/eBook/03.4.md | 50 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/en/eBook/03.4.md b/en/eBook/03.4.md index b367689b..08062cfb 100644 --- a/en/eBook/03.4.md +++ b/en/eBook/03.4.md @@ -1,12 +1,12 @@ # 3.4 Get into http package -In previous sections, we learned the work flow of web, and talked about a little about `http` package. In this section, we are going to learn two core functions in `http` package: Conn, ServeMux. +In previous sections, we learned about the work flow of the web and talked a little bit about Go's `http` package. In this section, we are going to learn about two core functions in the `http` package: Conn and ServeMux. ## goroutine in Conn -Unlike normal HTTP servers, Go uses goroutine for every affair that created by Conn in order to achieve high concurrency and performance, so every affair is independent. +Unlike normal HTTP servers, Go uses goroutines for every job initiated by Conn in order to achieve high concurrency and performance, so every job is independent. -Go uses following code to wait for new connections from clients. +Go uses the following code to wait for new connections from clients. c, err := srv.newConn(rw) if err != nil { @@ -14,16 +14,16 @@ Go uses following code to wait for new connections from clients. } go c.serve() -As you can see, it creates goroutine for every connection, and passes handler that is able to read data from request to the goroutine. +As you can see, it creates a new goroutine for every connection, and passes the handler that is able to read data from the request to the goroutine. ## Customized ServeMux -We used default router in previous section when talked about conn.server, the router passed request data to back-end handler. +We used Go's default router in previous sections when discussing conn.server, with the router passing request data to a back-end handler. -The struct of default router: +The struct of the default router: type ServeMux struct { - mu sync.RWMutex // because of concurrency, we have to use mutex here + mu sync.RWMutex // because of concurrency, we have to use a mutex here m map[string]muxEntry // router rules, every string mapping to a handler } @@ -40,7 +40,7 @@ The interface of Handler: ServeHTTP(ResponseWriter, *Request) // routing implementer } -`Handler` is a interface, but the function `sayhelloName` didn't implement this interface, why could we add it as handler? Because there is another type `HandlerFunc` in `http` package. We called `HandlerFunc` to define our `sayhelloName`, so `sayhelloName` implemented `Handler` at the same time. it's like we call `HandlerFunc(f)`, and function `f` is forced converted to type `HandlerFunc`. +`Handler` is an interface, but if the function `sayhelloName` didn't implement this interface, then how did we add it as handler? The answer lies in another type called `HandlerFunc` in the `http` package. We called `HandlerFunc` to define our `sayhelloName` method, so `sayhelloName` implemented `Handler` at the same time. It's like we're calling `HandlerFunc(f)`, and the function `f` is force converted to type `HandlerFunc`. type HandlerFunc func(ResponseWriter, *Request) @@ -49,9 +49,9 @@ The interface of Handler: f(w, r) } -How the router calls handlers after we set router rules? +How does the router call handlers after we set the router rules? -The router calls `mux.handler.ServeHTTP(w, r)` when it receives requests. In other words, it calls `ServeHTTP` interface of handlers. +The router calls `mux.handler.ServeHTTP(w, r)` when it receives requests. In other words, it calls the `ServeHTTP` interface of the handlers which have implemented it. Now, let's see how `mux.handler` works. @@ -70,9 +70,9 @@ Now, let's see how `mux.handler` works. return h } -The router uses URL as a key to find corresponding handler that saved in map, and calls handler.ServeHTTP to execute functions to handle data. +The router uses the request's URL as a key to find the corresponding handler saved in the map, then calls handler.ServeHTTP to execute functions to handle the data. -You should understand the router work flow now, and Go actually supports customized routers. The second argument of `ListenAndServe` is for configuring customized router, it's a interface of `Handler`. Therefore, any router implements interface `Handler` that can be used. +You should understand the default router's work flow by now, and Go actually supports customized routers. The second argument of `ListenAndServe` is for configuring customized routers. It's an interface of `Handler`. Therefore, any router that implements the `Handler` interface can be used. The following example shows how to implement a simple router. @@ -106,27 +106,27 @@ The following example shows how to implement a simple router. ## Go code execution flow -Let's take a look at the list of whole execution flow. +Let's take a look at the whole execution flow. - Call `http.HandleFunc` 1. Call HandleFunc of DefaultServeMux 2. Call Handle of DefaultServeMux 3. Add router rules to map[string]muxEntry of DefaultServeMux - Call `http.ListenAndServe(":9090", nil)` - 1. Instantiated Server - 2. Call ListenAndServe of Server - 3. Call net.Listen("tcp", addr) to listen to port. - 4. Start a loop, and accept requests in loop body. - 5. Instantiated a Conn and start a goroutine for every request: `go c.serve()`. - 6. Read request data: `w, err := c.readRequest()`. - 7. Check handler is empty or not, if it's empty then use DefaultServeMux. - 8. Call ServeHTTP of handler. - 9. Execute code in DefaultServeMux in this case. + 1. Instantiate Server + 2. Call ListenAndServe method of Server + 3. Call net.Listen("tcp", addr) to listen to port + 4. Start a loop and accept requests in the loop body + 5. Instantiate a Conn and start a goroutine for every request: `go c.serve()` + 6. Read request data: `w, err := c.readRequest()` + 7. Check whether handler is empty or not, if it's empty then use DefaultServeMux + 8. Call ServeHTTP of handler + 9. Execute code in DefaultServeMux in this case 10. Choose handler by URL and execute code in that handler function: `mux.handler.ServeHTTP(w, r)` 11. How to choose handler: - A. Check router rules for this URL. - B. Call ServeHTTP in that handler if there is one. - C. Call ServeHTTP of NotFoundHandler otherwise. + A. Check router rules for this URL + B. Call ServeHTTP in that handler if there is one + C. Call ServeHTTP of NotFoundHandler otherwise ## Links