Edited 03.4.md for grammar, typos and improved clarity

This commit is contained in:
Anchor
2014-09-09 23:14:34 -07:00
committed by James Miranda
parent 73e8d56952
commit 0f4501c696

View File

@@ -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