1. 函数类型
2. 结构体类型
3. 接口类型
4. 方法类型
5. 自定义类型
1. http.HandleFunc(pattern string, handler func(ResponseWriter, *Request))
2. http.ListenAndServe()
3. http.Serve(l net.Listener, handler Handler)
4. http.Handle(pattern string, handler Handler)
5. http.NewServeMux()
1. type Server struct
2. type ServeMux struct
3. type muxEntry struct
4. type conn struct
5. type serverHandler struct
1. type Handler interface
2. type ResponseWriter interface
3. type Flusher interface
1. func (srv *Server) ListenAndServe() error
2. func (srv *Server) Serve(l net.Listener) error
3. func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string)
4. func (mux *ServeMux) handler(host, path string)
5. func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)
6. func (mux *ServeMux) Handle(pattern string, handler Handler)
7. func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))
8. func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request)
9. func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)
// 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.
1. type HandlerFunc func(ResponseWriter, *Request)
2.1 http.HandleFunc(pattern string, handler func(ResponseWriter, *Request))
// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
2.2 http.ListenAndServe()
// ListenAndServe listens on the TCP network address addr and then calls
// Serve with handler to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
// The handler is typically nil, in which case the DefaultServeMux is used.
// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
2.3 http.Serve(l net.Listener, handler Handler)
// Serve accepts incoming HTTP connections on the listener l,
// creating a new service goroutine for each. The service goroutines
// read requests and then call handler to reply to them.
//
// The handler is typically nil, in which case the DefaultServeMux is used.
//
// HTTP/2 support is only enabled if the Listener returns *tls.Conn
// connections and they were configured with "h2" in the TLS
// Config.NextProtos.
//
// Serve always returns a non-nil error.
func Serve(l net.Listener, handler Handler) error {
srv := &Server{Handler: handler}
return srv.Serve(l)
}
2.4 http.Handle(pattern string, handler Handler)
// Handle registers the handler for the given pattern
// in the DefaultServeMux.
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
2.5 http.NewServeMux()
// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux { return new(ServeMux) }
以下结构体类型只列出重要成员
3.1 type Server struct
type Server struct {
Addr string // TCP address to listen on, ":http" if empty
Handler Handler // handler to invoke, http.DefaultServeMux if nil
...
}
3.2 type ServeMux struct
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
hosts bool // whether any patterns contain hostnames
}
3.3 type muxEntry struct
type muxEntry struct {
h Handler
pattern string
}
3.4 type conn struct
type conn struct {
// server is the server on which the connection arrived.
// Immutable; never nil.
server *Server
// rwc is the underlying network connection.
// This is never wrapped by other types and is the value given out
// to CloseNotifier callers. It is usually of type *net.TCPConn or
// *tls.Conn.
rwc net.Conn
...
}
3.5 type serverHandler struct
// serverHandler delegates to either the server's Handler or
// DefaultServeMux and also handles "OPTIONS *" requests.
type serverHandler struct {
srv *Server
}
4.1 type Handler interface
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
4.2 type ResponseWriter interface
type ResponseWriter interface{
Header() Header
Write([]byte) (int, error)
WriteHeader(statusCode int)
}
4.3 type Flusher interface
type Flusher interface{
// Flush sends any buffered data to the client.
Flush()
}
5.1 func (srv *Server) ListenAndServe() error
// ListenAndServe listens on the TCP network address srv.Addr and then
// calls Serve to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
//
// If srv.Addr is blank, ":http" is used.
//
// ListenAndServe always returns a non-nil error. After Shutdown or Close,
// the returned error is ErrServerClosed.
func (srv *Server) ListenAndServe() error {
if srv.shuttingDown() {
return ErrServerClosed
}
addr := srv.Addr
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}
5.2 func (srv *Server) Serve(l net.Listener) error
// Serve accepts incoming connections on the Listener l, creating a
// new service goroutine for each. The service goroutines read requests and
// then call srv.Handler to reply to them.
//
// HTTP/2 support is only enabled if the Listener returns *tls.Conn
// connections and they were configured with "h2" in the TLS
// Config.NextProtos.
//
// Serve always returns a non-nil error and closes l.
// After Shutdown or Close, the returned error is ErrServerClosed.
func (srv *Server) Serve(l net.Listener) error {
if fn := testHookServerServe; fn != nil {
fn(srv, l) // call hook with unwrapped listener
}
l = &onceCloseListener{Listener: l}
defer l.Close()
if err := srv.setupHTTP2_Serve(); err != nil {
return err
}
if !srv.trackListener(&l, true) {
return ErrServerClosed
}
defer srv.trackListener(&l, false)
var tempDelay time.Duration // how long to sleep on accept failure
baseCtx := context.Background() // base is always background, per Issue 16220
ctx := context.WithValue(baseCtx, ServerContextKey, srv)
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)
}
}
5.3 func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string)
// Handler returns the handler to use for the given request,
// consulting r.Method, r.Host, and r.URL.Path. It always returns
// a non-nil handler. If the path is not in its canonical form, the
// handler will be an internally-generated handler that redirects
// to the canonical path. If the host contains a port, it is ignored
// when matching handlers.
//
// The path and host are used unchanged for CONNECT requests.
//
// Handler also returns the registered pattern that matches the
// request or, in the case of internally-generated redirects,
// the pattern that will match after following the redirect.
//
// If there is no registered handler that applies to the request,
// Handler returns a ``page not found'' handler and an empty pattern.
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
// CONNECT requests are not canonicalized.
if r.Method == "CONNECT" {
// If r.URL.Path is /tree and its handler is not registered,
// the /tree -> /tree/ redirect applies to CONNECT requests
// but the path canonicalization does not.
if u, ok := mux.redirectToPathSlash(r.URL.Host, r.URL.Path, r.URL); ok {
return RedirectHandler(u.String(), StatusMovedPermanently), u.Path
}
return mux.handler(r.Host, r.URL.Path)
}
// All other requests have any port stripped and path cleaned
// before passing to mux.handler.
host := stripHostPort(r.Host)
path := cleanPath(r.URL.Path)
// If the given path is /tree and its handler is not registered,
// redirect for /tree/.
if u, ok := mux.redirectToPathSlash(host, path, r.URL); ok {
return RedirectHandler(u.String(), StatusMovedPermanently), u.Path
}
if path != r.URL.Path {
_, pattern = mux.handler(host, path)
url := *r.URL
url.Path = path
return RedirectHandler(url.String(), StatusMovedPermanently), pattern
}
return mux.handler(host, r.URL.Path)
}
5.4 func (mux *ServeMux) handler(host, path string)
// 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
}
5.5 func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)
// 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()
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)
}
if mux.m == nil {
mux.m = make(map[string]muxEntry)
}
mux.m[pattern] = muxEntry{h: handler, pattern: pattern}
if pattern[0] != '/' {
mux.hosts = true
}
}
5.6 func (mux *ServeMux) Handle(pattern string, handler Handler)
// 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()
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)
}
if mux.m == nil {
mux.m = make(map[string]muxEntry)
}
mux.m[pattern] = muxEntry{h: handler, pattern: pattern}
if pattern[0] != '/' {
mux.hosts = true
}
}
5.7 func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))
// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
}
5.8 func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
5.9 func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler
if handler == nil {
handler = DefaultServeMux
}
if req.RequestURI == "*" && req.Method == "OPTIONS" {
handler = globalOptionsHandler{}
}
handler.ServeHTTP(rw, req)
}
最简单的添加Web服务的方法:使用默认路由DefaultSeverMux
第一步 :调用http.HandleFunc("/hello",sayHello)设置访问路由
第二步 :调用http.ListenAndServer(“localhost:8088”,nil)设置端口并开始监听
具体代码如下
package main
import (
"fmt"
"net/http"
"strings"
"log"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //解析参数,默认是不会解析的
fmt.Println(r.Form) //这些信息是输出到服务器端的打印信息
fmt.Println("path", r.URL.Path)
fmt.Println("scheme", r.URL.Scheme)
fmt.Println(r.Form["url_long"])
for k, v := range r.Form {
fmt.Println("key:", k)
fmt.Println("val:", strings.Join(v, ""))
}
fmt.Fprintf(w, "Hello world!") //这个写入到w的是输出到客户端的
}
func main() {
http.HandleFunc("/", sayhelloName) //设置访问的路由
err := http.ListenAndServe("localhost:8088", nil) //设置监听的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
比较复杂的添加Web服务的方法:使用自定义路由Mux
package main
import (
"fmt"
"net/http"
)
type MyMux struct {
}
func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/hello" {
sayHello(w, r)
return
}
http.NotFound(w, r)
return
}
func sayHello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello world!")
}
func main() {
mux := &MyMux{}
http.ListenAndServe("localhost:8088", mux)//此处使用自定义的路由
}
更复杂添加Web服务的方法:使用自定义路由,使用http.Server结构体的方法监听服务
type MyServerMux struct {
Database string
RetentionPolicy string
Logger *zap.Logger
Config *Config
stats *Statistics
}
func (mux *MyServerMux ) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/metadata/put":
w.WriteHeader(http.StatusNoContent)
case "/api/put":
mux .servePut(w, r)
default:
http.NotFound(w, r)
}
}
func (mux *MyServerMux) servePut(w http.ResponseWriter, r *http.Request){
......
}
// serveHTTP handles connections in HTTP format.
func (s *Service) serveHTTP() {
myServerMux := &MyServerMux {
Database: s.Database,
RetentionPolicy: s.RetentionPolicy,
Logger: s.Logger,
stats: s.stats,
}
srv := &http.Server{Handler: myServerMux }//myServerMux 实现了Handler接口的ServeHTTP方法,是该接口的实现
srv.Serve(s.httpln)//此处的httpln实现了Listener接口的所有方法,是该接口的实现,传入之前需要设置地址
}
另一种做法是:将最后两行换成调用http.ListenAndServer(“localhost:8088”,myServerMux)。但实际上ListenAndServer(“localhost:8088”,myServerMux)调用的是func (srv *Server) ListenAndServe() error,如下
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}//此处根据传递的地址参数addr和handler,构造Server的实例,由实例调用ListenAndServe()方法
func (srv *Server) ListenAndServe()如下
func (srv *Server) ListenAndServe() error {
if srv.shuttingDown() {
return ErrServerClosed
}
addr := srv.Addr
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)//由实例传进来的地址开启监听服务
if err != nil {
return err
}
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})//等待客户端连接
}
可以看到,最后还是调用func (srv *Server) Serve(l net.Listener) error方法。
还有一种做法是:将最后两行换成http.Serve(s.httpln, s.Handler)。而该函数实际上是调用Server的func (srv *Server) Serve(l net.Listener)方法。
func Serve(l net.Listener, handler Handler) error {
srv := &Server{Handler: handler}
return srv.Serve(l)
}
func (srv *Server) Serve(l net.Listener) error {
if fn := testHookServerServe; fn != nil {
fn(srv, l) // call hook with unwrapped listener
}
l = &onceCloseListener{Listener: l}
defer l.Close()
if err := srv.setupHTTP2_Serve(); err != nil {
return err
}
if !srv.trackListener(&l, true) {
return ErrServerClosed
}
defer srv.trackListener(&l, false)
var tempDelay time.Duration // how long to sleep on accept failure
baseCtx := context.Background() // base is always background, per Issue 16220
ctx := context.WithValue(baseCtx, ServerContextKey, srv)
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)
}
}
所以这种方法,最后也是调用func (srv *Server) Serve(l net.Listener) error。
但是在调用func (srv *Server) Serve(l net.Listener) error之前,需要在实例化Server之前先传递一个路由器进来,如果没有传递,那么就是使用默认的路由器DefaultServeMux。如下所示。
func (c *conn) serve(ctx context.Context){}
通过对http包的分析之后,现在让我们来梳理一下整个的代码执行过程。
当我们使用默认的DefaultServeMux路由器时
当我们使用自定义的路由器时
3. 自定义路由器myMux,结构体类型,在结构体中定义所需变量。
4. 实现http.Handler接口的ServeHTTP()方法。
5. 自定义func(ResponseWriter, *Request)类型函数。
6. 在实现的ServeHTTP()方法中,根据r.URL.Path做分发。
7. 利用自定义的路由器myMux,实例化http.Server对象srv。
8. 设置监听端口net.Listener相关信息ln。
9. 利用对象srv调用Serve()方法,开启监听端口。srv.Serve(ln)。
10. 启动一个for循环,在循环体中Accept请求。
11. 对每个请求实例化一个Conn,并且开启一个goroutine为这个请求进行服务go c.serve()。
12. 读取每个请求的内容w, err := c.readRequest()。
13. 调用serverHandler{c.server}.ServeHTTP(w, w.req)方法。//此时ServeHTTP是serverHandler结构体的方法
14. 判断handler是否为空,如果没有设置handler(这个例子就没有设置handler),handler就设置为DefaultServeMux,否则,就是当前的handler。
15. 调用handler的ServeHTTP。//也即第5步中传入的路由器myMux的ServeHTTP方法
16. 具体的操作因具体路由器的ServeHTTP方法而异。//其实每一个路由器都是Handle接口的子类。因为都实现了ServeHTTP方法。
吐槽一下,看源码真**累。