Go(Golang.org)是在標准庫中提供HTTP協議支持的系統語言,通過他可以快速簡單的開發一個web服務器。同時,Go語言為開發者提供了很多便利。這本篇博客中我們將列出使用Go開發HTTP 服務器的方式,然后分析下這些不同的方法是如何工作,為什么工作的。
在開始之前,假設你已經知道Go的一些基本語法,明白HTTP的原理,知道什么是web服務器。然后我們就可以開始HTTP 服務器版本的著名的“Hello world”。
首先看到結果,然后再解釋細節這種方法更好一點。創建一個叫http1.go
的文件。然后將下面的代碼復制過去:
package main import ( "io" "net/http" ) func hello(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello world!") } func main() { http.HandleFunc("/", hello) http.ListenAndServe(":8000", nil) }
在終端執行go run http1.go
,然后再瀏覽器訪問http://localhost:8000。你將會看到Hello world!
顯示在屏幕上。
為什么會這樣?在Go語言里所有的可運行的包都必須命名為main
。我們創建了main和hello兩個函數。
在main函數中,我們從net/http
包中調用了一個http.HandleFucn
函數來注冊一個處理函數,在本例中是hello函數。這個函數接受兩個參數。第一個是一個字符串,這個將進行路由匹配,在本例中是根路由。第二個函數是一個func (ResponseWriter, Request)
的簽名。正如你所見,我們的hello函數就是這樣的簽名。下一行中的http.ListenAndServe(":8000", nil)
,表示監聽localhost的8000端口,暫時忽略掉nil。
在hello函數中我們有兩個參數,一個是http.ResponseWriter
類型的。它類似響應流,實際上是一個接口類型。第二個是http.Request
類型,類似於HTTP 請求。我們不必使用所有的參數,就想再hello函數中一樣。如果我們想返回“hello world”,那么我們只需要是用http.ResponseWriter,io.WriteString,是一個幫助函數,將會想輸出流寫入數據。
下面是一個稍微復雜的例子:
package main import ( "io" "net/http" ) func hello(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello world!") } func main() { mux := http.NewServeMux() mux.HandleFunc("/", hello) http.ListenAndServe(":8000", mux) }
在上面這個例子中,我們不在在函數http.ListenAndServe
使用nil
了。它被*ServeMux
替代了。你可能會猜這個例子跟我上面的例子是樣的。使用http注冊hanlder 函數模式就是用的ServeMux。
下面是一個更復雜的例子:
import ( "io" "net/http" ) func hello(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello world!") } var mux map[string]func(http.ResponseWriter, *http.Request) func main() { server := http.Server{ Addr: ":8000", Handler: &myHandler{}, } mux = make(map[string]func(http.ResponseWriter, *http.Request)) mux["/"] = hello server.ListenAndServe() } type myHandler struct{} func (*myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if h, ok := mux[r.URL.String()]; ok { h(w, r) return } io.WriteString(w, "My server: "+r.URL.String()) }
為了驗證你的猜想,我們有做了相同的事情,就是再次在屏幕上輸出Hello world。然而現在我們沒有定義ServeMux,而是使用了http.Server。這樣你就能知道為什么可以i是用net/http包運行了服務器了。