简易HTTP服务器的实现

net/http
package main

import (
    "io"
    "log"
    "net/http"
)

type myHandler struct{}

func (*myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "I'm home page")
}

func sayHello(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "hello world!")
}

func main() {
    // 设置路由
    http.Handle("/", &myHandler{})
    http.HandleFunc("/hello", sayHello)
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal(err)
    }
}
http://localhost:8080I'm home pagehttp://localhost:8080/hellohello world!

分析

http.Handle
// Handle registers the handler for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func Handle(pattern string, handler Handler) { 
    DefaultServeMux.Handle(pattern, handler) 
}
HandlerDefaultServeMux
// Handler是一个接口
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

// ServeMux是一个自定义类型
// ServeMux also takes care of sanitizing the URL request path,
// redirecting any request containing . or .. elements or repeated slashes
// to an equivalent, cleaner URL.
type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry //模式字符串与处理器的映射关系
    hosts bool // whether any patterns contain hostnames
}

// muxEntry 是一个自定义类型,包括一个模式字符串和对应的Handler接口
type muxEntry struct {
    h       Handler
    pattern string
}

var defaultServeMux ServeMux
// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = &defaultServeMux
DefaultServeMux*ServeMuxdefaultServeMuxServeMuxm*ServeMuxHandlem
// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
func (mux *ServeMux) Handle(pattern string, handler Handler) {
    mux.mu.Lock()
    defer mux.mu.Unlock()
    // 错误判断,模式字符串为空、处理起handler为空、对应的模式字符串的处理器已经存在
    if pattern == "" {
        panic("http: invalid pattern")
    }
    if handler == nil {
        panic("http: nil handler")
    }
    if _, exist := mux.m[pattern]; exist {
        panic("http: multiple registrations for " + pattern)
    }

    // 如果没有实例化,就make一下
    if mux.m == nil {
        mux.m = make(map[string]muxEntry)
    }
    mux.m[pattern] = muxEntry{h: handler, pattern: pattern}

    if pattern[0] != '/' {
        mux.hosts = true
    }
}
mux.m[pattern] = muxEntry{h: handler, pattern: pattern}handlerpatternmuxEntrymappatternmuxEntry
http.HandleDefaultServeMuxmmap[string]muxEntryurl
http.ListenAndServe
// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler}
    return server.ListenAndServe()
}
nilServerListenAndServe()listen
handlerServeHTTPserver.ListenAndServe()Accpetgo c.serve(ctx)c.serveserverHandler{c.server}.ServeHTTP(w, w.req)serverHandler*Server
// serverHandler delegates to either the server's Handler or
// DefaultServeMux and also handles "OPTIONS *" requests.
type serverHandler struct {
    srv *Server
}

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    // 重点, 取出内部的Handler接口变量
    handler := sh.srv.Handler
    // 如果是空,就是用默认的Handler
    if handler == nil {
        handler = DefaultServeMux
    }
    if req.RequestURI == "*" && req.Method == "OPTIONS" {
        handler = globalOptionsHandler{}
    }
    // 调用 ServeHTTP 方法!
    handler.ServeHTTP(rw, req)
}
serverHandlerServeHTTPHandlerServeHTTPServeHTTPHandlernilDefaultServeMuxServeHTTPDefaultServeMux*ServeMuxServeHTTP
// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
    if r.RequestURI == "*" {
        if r.ProtoAtLeast(1, 1) {
            w.Header().Set("Connection", "close")
        }
        w.WriteHeader(StatusBadRequest)
        return
    }
    h, _ := mux.Handler(r)
    h.ServeHTTP(w, r)
}

// handler is the main implementation of Handler.
// The path is known to be in canonical form, except for CONNECT methods.
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
    mux.mu.RLock()
    defer mux.mu.RUnlock()

    // Host-specific pattern takes precedence over generic ones
    if mux.hosts {
        h, pattern = mux.match(host + path)
    }
    if h == nil {
        h, pattern = mux.match(path)
    }
    if h == nil {
        h, pattern = NotFoundHandler(), ""
    }
    return
}
mux.Handlermux.matchmux.matchmux.mmapurlServeHTTP
http://localhost:8080myHandlerServeHTTPI'm home page
http.HandleFunchttp.Handlefunc(ResponseWriter, *Request)HandlerServeMuxmHandler
// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    mux.Handle(pattern, HandlerFunc(handler))
}

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

DefaultServeMuxHandleFunchandlerHandlerFuncHandlerHandlerServeHTTP
net/http

自定义路由器

DefaultServeMuxServeMux
package main

import (
    "io"
    "log"
    "net/http"
)

type myHandler struct{}

func (*myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "I'm home page")
}

func sayHello(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "hello world")
}

func main() {
    mux := http.NewServeMux() // new出一个新的ServeMux对象

    mux.Handle("/", &myHandler{})
    mux.HandleFunc("/hello", sayHello)
    err := http.ListenAndServe(":8080", mux) //传入自定义的路由器(mux)
    if err != nil {
        log.Fatal(err)
    }
}
http.NewServeMux()ServeMuxmux.Handlehttp.ListenAndServe
ServeMuxhttp.ListenAndServeServer
package main

import (
    "io"
    "log"
    "net/http"
    "time"
)

// 用字典实现路由器
var mux map[string]func(http.ResponseWriter, *http.Request)

// 自己实现的Handler
type myHandler struct{}

func (*myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // 根据url选择对应的处理函数
    if h, ok := mux[r.URL.String()]; ok {
        h(w, r)
        return
    }
    io.WriteString(w, "sorry, error happened!")
}

func sayHello(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "hello world")
}

func sayHome(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "I'm home page")
}

func main() {
    server := http.Server{
        Addr:        ":8080",
        Handler:     &myHandler{},
        ReadTimeout: 5 * time.Second, //设置超时时间
    }

    mux = make(map[string]func(http.ResponseWriter, *http.Request))
    mux["/"] = sayHome
    mux["/hello"] = sayHello
    err := server.ListenAndServe()
    if err != nil {
        log.Fatal(err)
    }
}

参考