首先,熟悉http协议的都知道,http协议是基于TCP实现的。

 http服务器的工作方式大概就是监听socket端口,接受连接,获取到请求,处理请求,返回响应。

 所以,对应的会有几个部分

Request:用户请求的信息。post、get、url等这些信息
Response: 返回给客户端的信息
Conn: 用户每次的连接请求
Handler:处理请求和返回信息的逻辑处理

func hello(w http.ResponseWriter,r *http.Request) {
  w.Write([]byte("hello!\r\n"))
}
func main() {
  http.HandleFunc("/",hello)
  err := http.ListenAndServe("0.0.0.0:8889",nil)
  if err != nil {
    fmt.Println(err)
  }
}

问题:函数  http.HandleFunc(“/”,hello)  里面发生了什么?

 先分析一下​​http.HandleFunc()​​这个函数。直接进入函数​​HandleFunc​​的声明,源码如下

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

DefaultServeMux = 默认的一个go web的路由器  在源代码中的声明如下

type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry
    hosts bool // whether any patterns contain hostnames
}

type muxEntry struct {
    explicit bool
    h        Handler
    pattern  string
}

// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux { 
    return &ServeMux{m: make(map[string]muxEntry)} 
}

// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = NewServeMux()

这里DefaultServeMux调用了HandleFunc(),参数就是传进来的​​“/”​​和​​HandleFunc​​(定义一个函数类型,就可以把函数作为参数传入) 

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

HandlerFunc 是ServeMux 结构体的方法,这里先分析​​HandlerFunc(handler)​​,也就是把​​func(ResponseWriter, *Request)​​函数类型转换为​​HandlerFunc​​类型(注意!是HandlerFunc,不是HandleFunc)【其实就是定制规则个人理解】

HandlerFunc这里定义了一个​​func(ResponseWriter, *Request)​​的函数类型,​​HandlerFunc(handler)​​实际上就是handler本身。为什么这么做?

type HandlerFunc func(ResponseWriter, *Request)

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

HandlerFunc实现了​​ServeHTTP(w ResponseWriter, r *Request)​​ 这个方法!!!!里面只有一行代码​​f(w, r)​​,也就是说实际上是调用handler,也就是我们一开始在​​http.HandleFunc(“/”, HandleRequest)​​中自己定义的函数HandleRequest。

而 HandlerFunc 实现了 ServeHTTP的方法,其实就是实现了 Handler 接口。

 HandlerFunc实现Handler接口里面的方法。跟Java里面的接口一样,任何实现接口的类型,都可以向上转换为该接口类型。这就意味着HandlerFunc类型的值可以自动转换为Handler类型的值作为参数传进任何函数中。这很重要!回头看看muxEntry结构体里面的两个变量​​pattern string​​和​​h Handler​​,不正好对应刚才传入的参数​​pattern, HandlerFunc(handler)​​吗!!

总结一下:
所以,​​HandlerFunc(handler)​​就是一个适配器模式!HandlerFunc实现Handler接口,ServeHTTP方法里面调用的实际上是我们一开始定义的函数HandleRequest。

这样的一个好处就是,​​func(ResponseWriter,*Request)​​ -> ​​HandlerFunc​​ -> ​​Handler​​ ,那定义的函数HandleRequest可以作为Handler类型的一个参数。调用Handler的ServeHTTP方法,也就是调用定义的函数HandleRequest。
理解完​​HandlerFunc(handler)​​,再来看看整句​​mux.Handle(pattern, HandlerFunc(handler))​​

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)
  }
  e := muxEntry{h: handler, pattern: pattern}
  mux.m[pattern] = e
  if pattern[len(pattern)-1] == '/' {
    mux.es = appendSorted(mux.es, e)
  }
  if pattern[0] != '/' {
    mux.hosts = true
  }
}

  个人思考:

原文地址:http://www.cnblogs.com/zh718594493/p/16911829.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性