Original link http://ironxu.com/779
Go Web Basic concepts and code reading 1. Go to build a simple Web service
The Go language provides a complete net/http package that can be easily built with HTTP packets to run a Web service. At the same time using this package can be very simple to the Web routing, static files, templates, cookies and other settings and operations.
$GOPATH/src/github.com/ironxu/go_note/web/basic/server.go Source code is as follows:
The HTTP package establishes the Web server packages
main
import (
"FMT"
"Log" "
net/http"
)
func sayhelloname (w http. Responsewriter, R *http. Request) {
r.parseform ()
FMT. Println ("Path:", R.url. Path)
FMT. fprintf (w, "Hello Go")
}
func main () {
http. Handlefunc ("/", Sayhelloname)
err: = http. Listenandserve (": 9090", nil)
if err! = Nil {
log. Fatal ("Listenandserver:", err)
}
}
Go run server.go can start the HTTP service and use the browser to open http://localhost:9090 to view the output. 2. Go Web Services explained
This section describes the Go Web services underlying implementation, including registration Routing and request handling 2.1 HTTP packet run mechanism
The Go Implementation Web service process creates a listen Socket, listens on the specified port, waits for a client request to arrive. The Listen socket accepts the client's request, obtains the customer socket, and then communicates with the client through the customer socket. Processing the client's request, first read the HTTP request from the client socket, then hand over to the corresponding handler processing request, and finally the handler processed data, through the client socket to clients.
This involves the concept of server-side: Request: User requested information to resolve the user's request information, including post, get, cookie, url and other information Conn: the user's every request link Handler: Processing the request and generating return information processing logic Response: Server needs feedback to clients 2.2 Service listener and request processing process
Go is through a Listenandserve listener service, underlying processing: initializing a server object and then calling net. Listen ("tcp", addr), monitor the ports we set up.
After monitoring the port, call srv. Serve (NET. Listener) function to handle request information from the receiving client. First receives the request through the listener, Second creates a conn, finally opened a goroutine, the request data as the parameter throws to this conn to serve. Go C.serve () Each request of the user is in a new goroutine to serve, does not affect each other.
Assign the appropriate function to process the request: Conn first parses Request:c.readrequest () and then gets the corresponding Handler:handler: = C.server.handler, which is the calling function Listenandserve The second parameter of the time, the example passes nil, which is null, then the default gets handler = Defaultservemux. Defaultservemux is a router that matches the URL to jump to its corresponding handle function
Call HTTP. The Handlefunc ("/", sayhelloname) function is to register the request/Routing rule, register the URL and handle function to the DEFAULTSERVEMUX variable, and finally call Defaultservemux's Servehttp method, This method internally calls the handle function.
The flowchart is as follows:
3. Web Service Code Implementation 3.1 routing registration Code
1 calls HTTP. Handlefunc ("/", Sayhelloname) registered routing
/usr/local/go/src/net/http/server.go:2081
func handlefunc (pattern string, handler func (Responsewriter, * Request) {
Defaultservemux.handlefunc (pattern, handler)//Defaultservemux type *servemux
}
2 Using the default Servemux
: 2027
func (Mux *servemux) Handlefunc (pattern string, handler func (Responsewriter, *request)) {
mux. Handle (Pattern, Handlerfunc (handler))
}
3 Registering a Routing policy defaultservemux
Func (Mux *servemux) Handle (pattern string, handler handler) {
mux.mu.Lock ()
defer mux.mu.Unlock ()
...
Mux.m[pattern] = muxentry{explicit:true, H:handler, Pattern:pattern}
if pattern[0]! = '/' {
mux.hosts = tr UE
}
...
}
Involving data structures
: 1900 Servemux Default instance is Defaultservemux
type servemux struct {
mu sync. Rwmutex//Lock, because the request involves concurrent processing, it requires a locking mechanism
m map[string]muxentry//Routing rules, a string corresponding to a MUX entity, where string is the registered route expression
hosts bool//whether in arbitrary rules with host information
}
Type muxentry struct {
explicit bool
h Handler//route processor
pattern string //URL match regular
}
type Handler interface {
servehttp (responsewriter, *request)
}
3.2 Service Monitoring Code
1 Call Err: = http. Listenandserve (": 9090", nil) listening port
/usr/local/go/src/net/http/server.go:2349
func listenandserve (addr string, handler handler) error {
server : = &server{addr:addr, Handler:handler}//Handler is empty
return Server. Listenandserve ()
}
Create a server object and call the server's Listenandserve ()
2 Listening to TCP ports
: 2210
func (SRV *server) listenandserve () error {
addr: = srv. Addr
If Addr = = "" {
Addr = ": http"
}
ln, err: = Net. Listen ("tcp", addr)
if err! = Nil {
return err
}
return srv. Serve (Tcpkeepalivelistener{ln. ( *net. TcpListener)})
}
3 Receiving Requests
: 2256
func (SRV *server) Serve (l net. Listener) Error {
defer l.close () ...
Basectx: = Context. Background ()
CTX: = context. Withvalue (Basectx, Servercontextkey, SRV)
CTX = context. Withvalue (CTX, Localaddrcontextkey, L.addr ())
for {
rw, E: = L.accept ()//1. Listener Receive request
if E! = nil {
...
}
Tempdelay = 0
c: = Srv.newconn (rw)//2. Create *conn
c.setstate (C.RWC, statenew)//Before Serve can return
go C.serve (CTX)//3. City a goroutine, the request data is passed as a parameter to Conn, the new goroutine to handle the request
}
}
4 Goroutine Processing Request
Serve a new connection.
Func (c *conn) serve (CTX context. Context) {
...
http/1.x on.
C.R = &CONNREADER{R:C.RWC}
c.bufr = Newbufioreader (C.R)
C.BUFW = Newbufiowritersize (checkconnerrorwriter {c}, 4<<10)
ctx, Cancelctx: = context. Withcancel (CTX)
defer cancelctx () for
{
W, err: = C.readrequest (CTX)//1. Get Request data
... Serverhandler{c.server}. Servehttp (W, w.req)//2. Process the request Serverhandler, corresponding to the 5th step below
w.cancelctx ()
if c.hijacked () {
return
}
w.finishrequest ()// 3. Return response result
if!w.shouldreuseconnection () {
if W.requestbodylimithit | | w.closedrequestbodyearly () {
C.closewriteandwait ()
}
return
}
c.setstate (C.RWC, Stateidle)
}
}
5 Processing Requests
Func (Sh serverhandler) servehttp (rw responsewriter, req *request) {
handler: = Sh.srv.Handler
If handler = = Nil {
handler = defaultservemux//Servemux
}
If req. RequestUri = = "*" && req. Method = = "OPTIONS" {
handler = globaloptionshandler{}
}
handler. Servehttp (rw, req)
}
5.1 handler. Servehttp (rw, req)
Func (Mux *servemux) servehttp (w responsewriter, R *request) {
if R.requesturi = = "*" {
if R.protoatleast (1, 1) {
W.header (). Set ("Connection", "Close")
}
W.writeheader (statusbadrequest)
return
}
h, _: = Mux. Handler (R)//Handlerfunc, Handler
h.servehttp (W, R)
}
5.2 Performing processing
Servehttp calls F (W, R).
Func (f Handlerfunc) servehttp (w responsewriter, R *request) {
f (W, R)
}
Types of data involved
Type Server struct {
Addr string //TCP address to listen on, ": http" if empty
Handler Handler // Handler to invoke, HTTP. Defaultservemux if nil
readtimeout time . Duration//maximum Duration before timing out read of the request
writetimeout time. Duration//maximum Duration before timing out write of the response
...
}
Type conn struct {
server *server//server is the server on which the connection arrived.
RWC net. Conn//RWC is the underlying network connection. It is usually of type *net. Tcpconn or *tls.conn.
REMOTEADDR string//This is the value of a Handler ' s (*request). Remoteaddr.
Mu sync. Mutex//MU guards Hijackedv, use of BUFR, (*response). Closenotifych.
...
}
Type Serverhandler struct {
srv *server
}
3.3 The Go code execution process
Call Http.handlefunc, in order to do a few things: Call the Defaultservemux Handlefunc call Defaultservemux handle to Defaultservemux] Add corresponding handler and routing rules in Muxentry
Call HTTP. Listenandserve (": 9090", nil), in order to do a few things: Instantiate the server calling the server's Listenandserve () call net. The Listen ("TCP", addr) listener port initiates a for loop in which the accept request instantiates a conn for each request and opens a goroutine for the request to service go C.serve () reads the contents of each request W, err: = C.readrequest () Determines whether the handler is empty, if no handler is set (this example does not set handler), handler is set to Defaultservemux call handler Servehttp In this example, the following goes into defaultservemux.servehttp according to request select Handler, and enters into this handler servehttp Mux.handler (R). Servehttp (W, R) Select handler:
A determine if there is a route to satisfy this request (looping through Servermux's muxentry)
B If there is a route to satisfy, call this route handler Servehttp
C If no route is met, call Notfoundhandler's Servehttp 4. Custom Routing Implementation
Define the type implementation Servehttp method, you can implement the custom route
Package main
Import (
"FMT"
"Log" "
net/http"
)
type mymux struct {}
func (P *mymux) Servehttp (w http. Responsewriter, R *http. Request) {
if r.url. Path = = "/" {
sayhelloname (W, R)
return
}
http. NotFound (W, R)
return
}
func sayhelloname (w http. Responsewriter, R *http. Request) {
r.parseform ()
FMT. Println ("Path:", R.url. Path)
FMT. fprintf (w, "Hello Go")
}
func main () {
mux: = &mymux{}
Err: = http. Listenandserve (": 9090", MUX)
if err! = Nil {
log. Fatal ("Listenandserver:", err)
}
}
Reference3.2 Go to build a Web server 3.3 go how to make the Web Work 3.4 go HTTP package detailed
You can follow my Weibo for more information: @ Just small yards farm