1. 程式人生 > >Golang內建庫學習筆記(2)-web服務器相關

Golang內建庫學習筆記(2)-web服務器相關

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服務器相關