Go_默认路由源码分析

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  在这个方法内部则是直接调用自己(因为本身就是个函数)然后就是具体外部的方法实现了



本文来自:CSDN博客

感谢作者:u012807459

查看原文:Go_默认路由源码分析

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。