Go_默认路由源码分析

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

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_默认路由源码分析

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

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