net/http 包
如果想使用Go建立一个web程序和web APIs,或者建立一个简单的HTTP服务器,最重要的就是标准库的net/http包,提供了web应用的全部基础组件.当然我们也可以进行拓展,开发出自己的框架.目前有beego,revel,martini.对于web开发,net/http,html/template是最主要的包,使用这两个基础的包,就能开发出全部功能的web应用.
net/http包有两个主要的组件:ServeMux(路由),Handler(句柄)
ServeMux
ServeMux 多路复用器(HTTP请求路由),对应着客户端的每个请求,从而调用请求的相应的handler.
Handler
Handlers主要是响应请求,对响应头和主体写入数据(就是服务器对一个客户端过来的一个请求进行相应的操作,比如输出信息给客户端,找不到对应的服务等).在Go,任何的对象都可以作为一个handler,这得益于Go语言的出色的面向接口思想.任意的对象(struct,function常见)只要实现了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 结构体实现了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)
}
在浏览器输入对应的路径就能打印出相应的信息
使用方法(函数)作为 Handlers
在上面的例子,使用结构体struct,实现了http.handler接口,从而作为了handler,比较"麻烦",还有更好的方式来实现:使用函数作为handler,只要这个函数的返回值是http.Handler
1.http.HandlerFunc类型
可以使用http.HandlerFunc类型来得到一个HTTP的handler,可以把任意一个有func(http.ResponseWriter, http.Request)标示的函数转换为一个HandlerFunc. HandlerFunc类型
内置了方法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开发")
}
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)
}
有一种情况:假如想传递数据库的链接对象到一个handler函数中,从而在函数重用他.可以写一个函数,用一个参数接收值,然后返回值是http.Handler.在Go中,可以使用闭包(closure,匿名函数).
代码栗子
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)
}
这种方式对于实际工作中非常有用,可以为程序的handler函数的上下文,提供有用的值.(明天学习Web Development with Go ServeMux.HandleFunc Function)