Golang內建庫學習筆記(2)-web服務器相關
阿新 • • 發佈:2018-05-14
c中 issue hook col err orm 服務器 srv per
package main import ( "net/http" "fmt" "strings" "log" ) func sayHelloName(w http.ResponseWriter, r *http.Request) { r.ParseForm() fmt.Println(r.Form) fmt.Println("url", r.URL.Path) fmt.Println("scheme", r.URL.Scheme) fmt.Println(r.Form["url_long"]) for k, v:=range r.Form { fmt.Println("key:", k) fmt.Println("value:", strings.Join(v, "")) } fmt.Fprintln(w, "hello web") } func main() { http.HandleFunc("/", sayHelloName) err := http.ListenAndServe(":9876", nil) if err!= nil { log.Fatal("ListenAndServe ", err) } }
先看一個最基本的golang的web服務器代碼。main中在HandleFunc中設置了路由,然後調用ListenAndServe選擇監聽的接口和路由方法(這裏路由方法制空,即調用了默認的路由,即HandleFunc設置的路由)。
LestenAndServe調用了http庫中的serve方法,代碼如下:
func (srv *Server) Serve(l net.Listener) error { defer l.Close() if fn := testHookServerServe; fn != nil { fn(srv, l) } var tempDelay time.Duration // how long to sleep on accept failure if err := srv.setupHTTP2_Serve(); err != nil {return err } srv.trackListener(l, true) defer srv.trackListener(l, false) baseCtx := context.Background() // base is always background, per Issue 16220 ctx := context.WithValue(baseCtx, ServerContextKey, srv) for { rw, e := l.Accept() if e != nil { select { case <-srv.getDoneChan(): return ErrServerClosed default: } if ne, ok := e.(net.Error); ok && ne.Temporary() { if tempDelay == 0 { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 } if max := 1 * time.Second; tempDelay > max { tempDelay = max } srv.logf("http: Accept error: %v; retrying in %v", e, tempDelay) time.Sleep(tempDelay) continue } return e } tempDelay = 0 c := srv.newConn(rw) c.setState(c.rwc, StateNew) // before Serve can return go c.serve(ctx) } }
可以看到,serve建立了一個循環來監聽請求。在接收到連接請求後,先接受請求,然後新建了連接,並利用go新建了線程來處理新的連接。這就是golang在處理web請求上支持高並發的根本。同時也保證了每個連接的獨立性。
Golang內建庫學習筆記(2)-web服務器相關