当前位置: 首页 > 工具软件 > Web.Go > 使用案例 >

golang学习之go web 开发http.HandleFunc、http.ListenAndServe与http.Handler

范云
2023-12-01

一、hello world

1、定义处理器函数
2、绑定路由处理器函数
3、启动服务并监听服务端口

package main

import (
	"log"
	"net/http"
)
// 1、定义处理器函数
func helloHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello world"))
}

func main() {
	// 2、绑定 路由"/hello"和处理器函数helloHandler
	http.HandleFunc("/hello", helloHandler)
	// 3、启动服务并监听8090端口
	err := http.ListenAndServe("localhost:8090", nil)
	if err != nil {
		log.Fatal(err)
	}
}

二、http.HandleFunc

1、从hello world代码中可以看到HandleFunc的功能是绑定路由处理器函数,跟进HandleFunc源码

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	DefaultServeMux.HandleFunc(pattern, handler)
}

2、跟进DefaultServeMux可以看到是ServeMux结构体类型变量

var DefaultServeMux = &defaultServeMux
var defaultServeMux ServeMux

3、跟进ServeMux结构体,可以看到包含一个map[string]muxEntry类型字段m

type ServeMux struct {
	mu    sync.RWMutex
	m     map[string]muxEntry
	es    []muxEntry // slice of entries sorted from longest to shortest.
	hosts bool       // whether any patterns contain hostnames
}

4、跟进DefaultServeMux.HandleFunc,DefaultServeMux.HandleFunc内部调用mux.Handle

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	if handler == nil {
		panic("http: nil handler")
	}
	mux.Handle(pattern, HandlerFunc(handler))
}

5、跟进mux.Handle(已略去部分代码)

func (mux *ServeMux) Handle(pattern string, handler Handler) {
	// 封装路由器及处理器函数
	e := muxEntry{h: handler, pattern: pattern}
	// 绑定路由与对应处理器函数
	mux.m[pattern] = e
}

综上可以看到http.HandleFunc的功能是绑定路由及处理器函数并注册到DefaultServeMux的map内。

三、http.ListenAndServe

1、跟进源码,看到内部调用server.ListenAndServe()

func ListenAndServe(addr string, handler Handler) error {
	server := &Server{Addr: addr, Handler: handler}
	return server.ListenAndServe()
}

2、跟进server.ListenAndServe()(已略去部分代码)

func (srv *Server) ListenAndServe() error {
	return srv.Serve(ln)
}

3、跟进srv.Serve(ln) (已略去部分代码)最后一行看到,启动了一个协程 调用 c.serve(connCtx)

func (srv *Server) Serve(l net.Listener) error {
	go c.serve(connCtx)
}

4、跟进c.serve(connCtx)(已略去部分代码)看到一行如下代码

serverHandler{c.server}.ServeHTTP(w, w.req)

5、跟进ServeHTTP(w, w.req)(已略去部分代码),可以看到当handler为nil时使用默认Handler即DefaultServeMux

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
	handler := sh.srv.Handler
	if handler == nil {
		handler = DefaultServeMux
	}
	handler.ServeHTTP(rw, req)
}

6、跟进DefaultServeMux.ServeHTTP(rw, req)(已略去部分代码)

func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
	// 查询已注册的处理器函数
	h, _ := mux.Handler(r)
	// 调用注册的处理器函数
	h.ServeHTTP(w, r)
}

7、跟进mux.Handler( r )到最后一行代码(已略去部分代码)

func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
	return mux.handler(host, r.URL.Path)
}

8、跟进mux.handler(host, r.URL.Path),看到当找不到对应处理器函数时返回NotFoundHandler 404页面处理器函数

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
}

9、跟进mux.match(path),可以看到处理器函数就是http.HandleFunc注册到map中的

func (mux *ServeMux) match(path string) (h Handler, pattern string) {
	v, ok := mux.m[path]
	if ok {
		return v.h, v.pattern
	}
}

四、http.Handler

hello world 中http.ListenAndServe(“localhost:8090”, nil)出入的http.Handler是nil,当handler为nil时使用默认的handler。现在传入一个自定义http.Handler

package main

import (
	"log"
	"net/http"
)

type myHandler struct {
}

func (myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.URL.Path {
	case "/hello":
		helloHandler(w, r)
	default:
		http.NotFound(w, r)
	}
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello world"))
}

func main() {
	var handler myHandler
	err := http.ListenAndServe("localhost:8090", handler)
	if err != nil {
		log.Fatal(err)
	}
}

 类似资料: