golang的http包笔记

x87648510 · · 1644 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

最近打算用golang做项目,看了一下golang的资料,顺便做一下笔记,以供参考,复习.
由于对golang的熟悉度还不是很高,写的有点生疏了,也希望能对大家有帮助吧.

示例源码:
packagemain
import(
    "log"
    "net/http"
)
func sayHelloName
(w http.ResponseWriter,r*http.Request){
    w.Write([]byte("hello,world!"))
}
func main(){
    http.HandleFunc("/",sayHelloName)
    err:=http.ListenAndServe(":8080",nil)
    iferr!=nil{
        log.Fatal("ListenAndServe:",err)
    }
}
http.HandleFunc("/",sayHelloName) 解读
打开源码包 server.go跳到1775行,看到函数
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}
DefaultServeMux的结构如下:
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
}
DefaultServeMux是一个全局变量在server.go的 1595 行创建的
func NewServeMux() *ServeMux { return &ServeMux{m: make(map[string]muxEntry)} }
var DefaultServeMux = NewServeMux()
接着跟进 DefaultServeMux.HandleFunc(pattern, handler) 
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    mux.Handle(pattern, HandlerFunc(handler))
}
在这个函数里面把前面传进来的helloWorld 函数转换成 HandlerFunc
HandlerFunc的类型如下:
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}
HandlerFunc类型实现了方法 ServeHTTP
再跟进Handle函数
func (mux *ServeMux) Handle(pattern string, handler Handler) {
    mux.mu.Lock()   // 因为map是全局的,涉及到全局调用,因此加锁
    defer mux.mu.Unlock()
    if pattern == "" {
        panic("http: invalid pattern " + pattern)
    }
    if handler == nil {
        panic("http: nil handler")
    }
    if mux.m[pattern].explicit {
        panic("http: multiple registrations for " + pattern)
    }
    mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern} // 这里注册路由

  err := http.ListenAndServe(":8080",nil)解读
跟进函数ListenAndServe,内容如下
func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler}
    return server.ListenAndServe()
}
而参数 Handler 是一个接口,内容如下
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}
看到 server := &Server{Addr: addr, Handler: handler} 这句
因为我们在调用ListenAndServe时,第二个参数是nil,所以这里的handle是nil
继续跟进ListenAndServe内容如下
func (srv *Server) ListenAndServe() error {
    addr := srv.Addr
    if addr == "" {
        addr = ":http"
    }
    ln, err := net.Listen("tcp", addr)  // 在这里调用了tcp监听了
    if err != nil {
        return err
    }
    return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}
跟进 Serve,可以看到在该函数里面调用了rw, e := l.Accept(),在接受连接的函数
并且每一个连接 go c.serve() 创建了一个携程
跟进 c.serve() 可以看到在函数里面对请求调用了 ServeHTTP
serverHandler{c.server}.ServeHTTP(w, w.req) 
跟进去内容如下
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    handler := sh.srv.Handler
    if handler == nil { // 在在这里判断用哪个 handler了
        handler = DefaultServeMux
    }
    if req.RequestURI == "*" && req.Method == "OPTIONS" {
        handler = globalOptionsHandler{}
    }
    handler.ServeHTTP(rw, req)
}
很显然看出了,如果在调用err:=http.ListenAndServe(":8080",nil)时,第二个参数是
我们自定义的Handler的话则调用我们的,否则的话就默认调用 DefaultServeMux
由此可以看出,如果我们要自定义Handler的话只要实现ServeHTTP(ResponseWriter, *Request)方法即可
例子如下:
package main
import (
    "fmt"
    "log"
    "net/http"
)
type MyHandler struct {
}
func (this *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Println("myHanlder")
    w.Write([]byte("myHanlder"))
}
func main() {
    err := http.ListenAndServe(":8080", &MyHandler{})
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:x87648510

查看原文:golang的http包笔记

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1644 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传