您的位置:首页 > 编程语言 > Go语言

Go_默认路由源码分析

2014-06-07 13:42 627 查看
func main() {
http.HandleFunc("/say",say)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal(err.Error())
}
}

func say(w http.ResponseWriter, r *http.Request) {
//
}
上面是一段启动web服务的代码通过监听8080端口 并且在启动钱注册了say()函数

如在浏览器输入 localhost:8080/say就会默认回调say函数 今天就来分析一下这其中的大致过程

首先在go当中做请求转发可以使用系统默认的路由器也可以使用自己定制的路由器但是都必须要去实现Handler接口

type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
在路由这一个大量涉及到Handler这个接口不仅仅是自定义路由和默认路由要实现这个接口 甚至文章开头的例子中say函数在注册之后都是先强制类型转换为server.go中的HandleFunc类型 而又由于HandleFunc可以实现了ServeHttp方法 所以就实现了Handler接口  所以每一个注册的函数其实最后都被当做Handler类型来做处理

下面介绍路由请求分发的大致过程 

http.ListenerAndServer(addr,nil) 监听端口 addr 地址  第二个参数设置你自己实现的路由 如果为nil则使用默认的

通过返回的端口监听器监听addr端口  通过l.Aceept 接受连接 go c.serve()为该连接创建一个新的协程去专门处理 因为有for循环所以继续等待接受

func (srv *Server) Serve(l net.Listener) error {
defer l.Close()
var tempDelay time.Duration // how long to sleep on accept failure
for {
rw, e := l.Accept()
if e != nil {
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
}
log.Printf("http: Accept error: %v; retrying in %v", e, tempDelay)
time.Sleep(tempDelay)
continue
}
return e
}
tempDelay = 0
c, err := srv.newConn(rw)
if err != nil {
continue
}
go c.serve()
}
}


下图是个我自己总结的比较关键的几步 先看图 再解释



客户端来请求 然后接收 启动协程处理  其中serverHandler这一步是server.go内部私有的结构体用来判断是选择开发者自己实现的路由还是默认的路由 
无论是哪个路由 都是会调用该路由的ServeHTTP 然后路由在ServeHTTP内部自己处理具体的分发请求

如果是默认的路由则最终会根据路径 去匹配对应的Handler然后返回  注意这里的路径就是一开始注册的路径一个路径对应一个函数也就是一个Handler

将该Handler返回之后则调用该Handler的ServeHTTP  在这个方法内部则是直接调用自己(因为本身就是个函数)然后就是具体外部的方法实现了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: