net/http 包
如果想使用Go建立一個web程序和web APIs,或者建立一個簡單的HTTP服務(wù)器,最重要的就是標(biāo)準(zhǔn)庫的net/http包,提供了web應(yīng)用的全部基礎(chǔ)組件.當(dāng)然我們也可以進(jìn)行拓展,開發(fā)出自己的框架.目前有beego,revel,martini.對于web開發(fā),net/http,html/template是最主要的包,使用這兩個基礎(chǔ)的包,就能開發(fā)出全部功能的web應(yīng)用.
net/http包有兩個主要的組件:ServeMux(路由),Handler(句柄)
ServeMux
ServeMux 多路復(fù)用器(HTTP請求路由),對應(yīng)著客戶端的每個請求,從而調(diào)用請求的相應(yīng)的handler.
Handler
Handlers主要是響應(yīng)請求,對響應(yīng)頭和主體寫入數(shù)據(jù)(就是服務(wù)器對一個客戶端過來的一個請求進(jìn)行相應(yīng)的操作,比如輸出信息給客戶端,找不到對應(yīng)的服務(wù)等).在Go,任何的對象都可以作為一個handler,這得益于Go語言的出色的面向接口思想.任意的對象(struct,function常見)只要實(shí)現(xiàn)了http.Handler接口,就能作為http請求的handler.
http.Handler接口
type Handler interface{
ServeHTTP(ResponseWrite,* Request)
}
這是一些共用的handler
- FileServer
- NotFoundHandler
- RedirectHandler
- StripPrefix
- TimeoutHandler
自定義Handlers
type messageHandler struct{
message string
}
//implement http.Handler interface
func (m *messageHandler)ServeHTTP(w http.ResponseWrite,r *http.Request){
fmt.Fprintf(w,m.message)
}
messageHandler 結(jié)構(gòu)體實(shí)現(xiàn)了http.Handler接口,可以作為http請求的handler
- 使用自定義的Handler
// book
package main
import (
"fmt"
"log"
"net/http"
)
type messageHandler struct {
message string
}
//implement http.Handler interface
func (m *messageHandler) ServeHTTP(w http.ResponseWrite, r *http.Request) {
fmt.Fprintf(w, m.message)
}
func main() {
mux := http.NewServeMux()
mh1 := &messageHandler{"歡迎使用Go"}
mux.Handle("/welcome", mh1)
mh2 := &messageHandler{"Go這的很酷啊!"}
mux.Handle("/message", mh2)
log.Println("Listening...")
http.ListenAndServe(":9090", mux)
}
在瀏覽器輸入對應(yīng)的路徑就能打印出相應(yīng)的信息
使用方法(函數(shù))作為 Handlers
在上面的例子,使用結(jié)構(gòu)體struct,實(shí)現(xiàn)了http.handler接口,從而作為了handler,比較"麻煩",還有更好的方式來實(shí)現(xiàn):使用函數(shù)作為handler,只要這個函數(shù)的返回值是http.Handler
1.http.HandlerFunc類型
可以使用http.HandlerFunc類型來得到一個HTTP的handler,可以把任意一個有func(http.ResponseWriter, http.Request)標(biāo)示的函數(shù)轉(zhuǎn)換為一個HandlerFunc. HandlerFunc類型
內(nèi)置了方法ServeHTTP(http.ResponseWriter,http.Request),所以符合http.Handler接口,作為一個HTTP的handler
栗子如下
// book
package main
import (
"fmt"
"log"
"net/http"
)
func messageHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "歡迎使用Go開發(fā)")
}
func main() {
mux := http.NewServeMux()
//Convert the messageHandler function to a HandlerFunc type
mh := http.HandlerFunc(messageHandler)
mux.Handle("/welcome", mh)
log.Println("Listening...")
http.ListenAndServe(":9090", mux)
}
有一種情況:假如想傳遞數(shù)據(jù)庫的鏈接對象到一個handler函數(shù)中,從而在函數(shù)重用他.可以寫一個函數(shù),用一個參數(shù)接收值,然后返回值是http.Handler.在Go中,可以使用閉包(closure,匿名函數(shù)).
代碼栗子
package main
import (
"fmt"
"log"
"net/http"
)
//Writing Handler Logic into a Closure
func messageHandler(message string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, message)
})
}
func main() {
mux := http.NewServeMux()
mux.Handle("/welcome", messageHandler("歡迎使用Go"))
mux.Handle("/message", messageHandler("Hello Go!"))
log.Println("Listening...")
http.ListenAndServe(":9090", mux)
}
這種方式對于實(shí)際工作中非常有用,可以為程序的handler函數(shù)的上下文,提供有用的值.(明天學(xué)習(xí)Web Development with Go ServeMux.HandleFunc Function)