一.建立简单的WEB服务器
func helloworld(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //解析表单参数
fmt.Println(r.Form) //打印表单
fmt.Fprintf(w, "Hello world!") //写入ResponseWriter返回客户端
}
func main() {
http.HandleFunc("/", helloworld) //设置访问路由 任意地址匹配helloworld方法
err := http.ListenAndServe(":1234", nil) //设置监听端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
运行上面这段代码,程序将监听1234端口的http请求。将请求交给helloworld方法进行处理。
helloworld方法解释请求中的参数并打印,返回Hello world到客户端。
二.WEB工作方式
1.监听请求
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
通过ListenAndServe设置监听地址及Handler后,将创建一个server并开始监听请求
server.ListenAndServe会调用一个Serve方法
2.创建连接
func (srv *Server) Serve(l net.Listener) error {
defer l.Close()
if fn := testHookServerServe; fn != nil {
fn(srv, l)
}
var tempDelay time.Duration //接收失败后,将延迟一段时间再次执行
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)
ctx = context.WithValue(ctx, LocalAddrContextKey, l.Addr())
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)//将请求交给这个连接进行处理,创建一个goroutine
}
}
通过不断循环接收请求,并创建新的连接,调用serve处理请求。每一个请求都会创建一个goroutine,互不影响。
调用serve方法后,serve先在参数中取出Request。创建一个serverHandler并调用了它的ServeHTTP
serverHandler{c.server}.ServeHTTP(w, w.req)
3.处理请求
type serverHandler struct {
srv *Server
}
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler
if handler == nil {//如果server没有handler则使用默认的multiplexer
handler = DefaultServeMux
}
if req.RequestURI == "*" && req.Method == "OPTIONS" {
handler = globalOptionsHandler{}
}
handler.ServeHTTP(rw, req)
}
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
取得server的handler进行处理请求,实现handler接口需要一个ServeHTTP方法,该方法就是最终处理请求的方法
在第一节中,我们并没有写ServeHTTP方法。但在http.HandleFunc("/", sayhelloName)
中调用了HanleFunc
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
mux.Handle(pattern, HandlerFunc(handler))
}
HandleFunc为默认的multiplexer注册一个handler
三.总结
http.HandleFunc("/", helloworld)
err := http.ListenAndServe(":1234", nil)
只调用了两个方法就可以让WEB服务器跑起来
HanleFunc为默认的MUX注册handler,将匹配地址与处理方法绑定起来。处理方法接收 http.ResponseWriter、*http.Request两个类型的参数,无返回值。
然后用http.ListenAndServe开启对某端口进行监听。
1.ListenAndServe调用serve进行循环接收请求
2.serve接收到请求后新建连接并用一个新的goroutine进行处理,调用连接的serve方法
3.con.serve调用server的handler进行处理请求。如果server没有handler则使用默认的MUX——DefaultServeMux