標籤:使用 運行 handler 服務 unlock 論壇 count 並發 要求方法
使用Go語言,我們可以輕鬆建立出Web服務,這一點比Node.js還要簡單,今天就來總結一下Go語言中Web服務的建立方式。
首先,我們需要引入net/http
這個包來處理HTTP請求,然後在指定的連接埠開啟服務,下面來寫一個最簡單的Web服務程式:
// server.gopackage mainimport ( "fmt" "log" "net/http")func main() { http.HandleFunc("/", handler) log.Println("go server listening at port 3000...") err := http.ListenAndServe(":3000", nil) if err != nil { log.Fatal("err: ", err) }}func handler(res http.ResponseWriter, req *http.Request) { log.Println(req.URL.Path) fmt.Fprintf(res, "URL.Path = %q\n", req.URL.Path)}
上面代碼中,我們會處理所有3000
連接埠的請求,然後在頁面顯示請求的路徑
。另外,我們在代碼中引入了log
包,使用log.Println(s)
方法列印資訊,運行代碼後,在瀏覽器請求localhost:3000
及localhost:3000/test
,控制台列印資訊如下:
$ go run server.go2018/08/30 13:26:58 go server listening at port 3000...2018/08/30 13:27:01 /2018/08/30 13:27:07 /test
接下來,我們希望這個服務能夠解析出瀏覽器的請求資訊,返回並顯示到頁面,下面是經過改進後的代碼:
// server.gopackage mainimport ( "fmt" "log" "net/http")func main() { http.HandleFunc("/", handler) log.Println("go server listening at port 3000...") err := http.ListenAndServe(":3000", nil) if err != nil { log.Fatal("err: ", err) }}func handler(res http.ResponseWriter, req *http.Request) { // 要求方法 請求地址 協議類型 fmt.Fprintf(res, "%s %s %s\n", req.Method, req.URL, req.Proto) // 要求標頭資訊 for k, v := range req.Header { fmt.Fprintf(res, "Header[%q] = %q\n", k, v) } // 請求的伺服器URL & 請求的遠程地址 fmt.Fprintf(res, "Host = %q\n", req.Host) fmt.Fprintf(res, "RemoteAddr = %q\n", req.RemoteAddr) if err := req.ParseForm(); err != nil { log.Print(err) } // 表單資訊 for k, v := range req.Form { fmt.Fprintf(res, "Form[%q] = %q\n", k, v) }}
在handler
函數中,我們從http.Request
中取出相應的HTTP請求資訊,然後返回給瀏覽器,大家可以親自運行以上代碼,來觀察實際效果。
接下來,我們希望做個小功能 - 統計使用者的訪問次數,這是一項很古老的技術了,在上個世紀的論壇網站中曾廣泛應用。:)
我們改進後的代碼如下:
// server.gopackage mainimport ( "fmt" "log" "sync" "net/http")var mutex sync.Mutexvar count intfunc main() { http.HandleFunc("/", handler) // 添加/count路由及處理函數 http.HandleFunc("/count", counter) log.Println("go server listening at port 3000...") err := http.ListenAndServe(":3000", nil) if err != nil { log.Fatal("err: ", err) }}// 每次訪問時 count遞增func handler(res http.ResponseWriter, req *http.Request) { mutex.Lock() count++ mutex.Unlock() fmt.Fprintf(res, "URL.Path = %q\n", req.URL.Path)}// 顯示當前訪問次數func counter(res http.ResponseWriter, req *http.Request) { mutex.Lock() fmt.Fprintf(res, "Visit Count: %d\n", count) mutex.Unlock()}
這次我們引入了sync
包,來應對並發訪問帶來的資料更新問題,sync.Mutex
類提供了Lock()
和Unlock()
方法,分別對更新操作進行加鎖和解鎖,保證count
的遞增操作不會受到並發訪問的影響。
運行上面的代碼,然後在瀏覽器中訪問除/count
之外的路徑,都可以累積訪問次數,最後,在訪問/count
路徑時,會返回當前服務被訪問的次數。
Golang系列文章:建立Web服務