【golang】http.ListenAndServe源码解析

这篇具有很好参考价值的文章主要介绍了【golang】http.ListenAndServe源码解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

http.ListenAndServe

func ListenAndServe(addr string, handler Handler) error

ListenAndServe监听TCP地址addr,并且会使用handler参数调用Serve函数处理接收到的连接。handler参数一般会设为nil,此时会使用DefaultServeMux。

接下来我们看一下这个函数的主要源码流程。

一、通过ListenAndServe的参数创建Server结构体

func ListenAndServe(addr string, handler Handler) error {
	server := &Server{Addr: addr, Handler: handler}
	return server.ListenAndServe()
}

Server 定义运行HTTP服务器的参数。Server的零值是一个有效的配置。

第一层相当于封装了一下创建Server结构体的过程,更易于用户使用,创建Server结构体之后,调用Server结构体的ListenAndServe方法。

二、定义监听信息(Listen)调用Serve处理请求

func (srv *Server) ListenAndServe() error {
	if srv.shuttingDown() {
		return ErrServerClosed
	}
	addr := srv.Addr
	if addr == "" {
		addr = ":http"
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	return srv.Serve(ln)
}

ListenAndServe监听TCP网络地址 srv.Addr,然后调用服务来处理传入连接的请求。

第二层首先根据srv中Addr定义了监听信息ln, err := net.Listen("tcp", addr),然后把监听对象ln作为srv(Server)对象调用Serve方法的参数。

三、监听器持续监听并Accept请求创建连接,处理连接

func (srv *Server) Serve(l net.Listener) error {
	......
		for {
				rw, err := l.Accept() //接收
				if err != nil {
					if srv.shuttingDown() {
						return ErrServerClosed
					}
					if ne, ok := err.(net.Error); ok && ne.Temporary() {
						if tempDelay == 0 {
							tempDelay = 5 * time.Millisecond
						} else {
							tempDelay *= 2
						}
						if max := 1 * time.Second; tempDelay > max {
							tempDelay = max
						}
						srv.logf("http: Accept error: %v; retrying in %v", err, tempDelay)
						time.Sleep(tempDelay)
						continue
					}
					return err
				}
				connCtx := ctx
				if cc := srv.ConnContext; cc != nil {
					connCtx = cc(connCtx, rw)
					if connCtx == nil {
						panic("ConnContext returned nil")
					}
				}
				tempDelay = 0
				c := srv.newConn(rw) //创建新连接
				c.setState(c.rwc, StateNew, runHooks) // before Serve can return
				go c.serve(connCtx)  //开启单独协程处理连接
			}
		}

服务接收监听器上的传入连接,创建一个新的服务协程为每个连接。

Serve方法开启一个for循环,for循环中不断从监听器中接受每一个请求Accept,然后根据获取到的请求创建新的连接,最后开启一个新的协程服务go c.serve(connCtx)单独处理这个连接。

四、serve服务处理这个连接

func (c *conn) serve(ctx context.Context) {
	......
	serverHandler{c.server}.ServeHTTP(w, w.req)
	......
}

第四层主要流程serve函数中会判断是否为https连接,如果是就升级为https连接。接着创建读写文本,最后通过serverHandler结构体调用相应的ServeHTTP方法处理。

五、ServeHttp具体处理逻辑

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
	handler := sh.srv.Handler
	if handler == nil {
		handler = DefaultServeMux
	}
	if !sh.srv.DisableGeneralOptionsHandler && req.RequestURI == "*" && req.Method == "OPTIONS" {
		handler = globalOptionsHandler{}
	}

	handler.ServeHTTP(rw, req)
}

第五层主要流程是如果server结构中自带了相应的Handler对象的话,就调用handler自己实现的ServeHTTP函数,如果没有自带的话,就使用标准库中默认DefaultServeMux作为handler。

六、DefaultServeMux默认处理逻辑

//部分源码
type ServeMux struct {
	mu    sync.RWMutex
	m     map[string]muxEntry
	es    []muxEntry 
	hosts bool       
}

type muxEntry struct {
	h       Handler
	pattern string
}

var DefaultServeMux = &defaultServeMux

var defaultServeMux ServeMux

......

func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
	if r.RequestURI == "*" {
		if r.ProtoAtLeast(1, 1) {
			w.Header().Set("Connection", "close")
		}
		w.WriteHeader(StatusBadRequest)
		return
	}
	h, _ := mux.Handler(r)
	h.ServeHTTP(w, r)
}

可以看到DefaultServeMux就是ServeMux数据结构的实例对象,标准库中路由注册的默认数据结构是map,key是接口的字符串,value是处理器。

第六层的主要流程处理逻辑为先使用request为参数,通过调用ServeMux中Handler方法查询ServeMux对象中的map,得到相应的handler,handler调用ServeHTTP函数处理。

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}
  • 如果用户自定义实现了Handler,那么根据相应路径在map中查询到相对应的Handler,然后再调用用户自定义的ServeHTTP处理请求。

  • 如果用户没有自定义Handler,只注册了对应处理函数(使用了http.HandleFunc),那么就会根据默认DefaultServeMux去map查询到这个函数类型Handler,然后再调用ServeHTTP处理函数。下面就是对应部分源码,可以看到,调用的ServeHTTP中又回调了用户自定义的函数。

type HandlerFunc func(ResponseWriter, *Request)

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

总结

以上就是当调用接口时候ListenAndServe的大致流程。而其实不管是Golang本身标准库或者是市面上许多go-web框架也好,都是先把对应接口请求和处理加入到某个数据结构中,然后监听请求,被调用时,再去这个数据结构中查询再进行处理。文章来源地址https://www.toymoban.com/news/detail-844635.html

到了这里,关于【golang】http.ListenAndServe源码解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • linux高并发web服务器开发(web服务器)18_函数解析http请求, 正则表达式,sscanf使用,http中数据特殊字符编码解码

    pdf详情版 编写函数解析http请求 ○ GET /hello.html HTTP/1.1rn ○ 将上述字符串分为三部分解析出来 编写函数根据文件后缀,返回对应的文件类型 sscanf - 读取格式化的字符串中的数据 ○ 使用正则表达式拆分 ○ [^ ]的用法 通过浏览器请求目录数据 ○ 读指定目录内容  opendir 

    2024年02月16日
    浏览(60)
  • Golang Gin HTTP 请求和参数解析

    我们介绍了Gin框架,并做了Gin框架的安装,完成了第一个Gin工程的创建。 创建Engine 在gin框架中,Engine被定义成为一个结构体,Engine代表gin框架的一个结构体定义, 其中包含了路由组、中间件、页面渲染接口、框架配置设置等相关内容。 默认的Engine可以通过gin.Default进行创建

    2024年02月01日
    浏览(79)
  • Go For Web:一篇文章带你用 Go 搭建一个最简单的 Web 服务、了解 Golang 运行 web 的原理

    本文作为解决如何通过 Golang 来编写 Web 应用这个问题的前瞻,对 Golang 中的 Web 基础部分进行一个简单的介绍。目前 Go 拥有成熟的 Http 处理包,所以我们去编写一个做任何事情的动态 Web 程序应该是很轻松的,接下来我们就去学习了解一些关于 Web 的相关基础,了解一些概念,

    2023年04月14日
    浏览(51)
  • golang http transport源码分析

    Golang http库在日常开发中使用会很多。这里通过一个demo例子出发,从源码角度梳理golang http库底层的数据结构以及大致的调用流程 先看看http.Client结构体,如下: Transport:http client实际发送请求结构体 Timeout:http client请求超时设置(后续在详细分析) 在看Transport结构体(net/http

    2024年02月11日
    浏览(35)
  • golang通过go-git下载gitlab源码

    1 申请令牌 方法1:具体项目下申请: 方法2:全局申请 2 获取token 3 下载代码 替换下面: username token 参考: https://docs.gitlab.cn/jh/user/profile/personal_access_tokens.html

    2024年01月24日
    浏览(48)
  • 【Golang】go编程语言适合哪些项目开发?

    前言 在当今数字化时代,软件开发已成为各行各业的核心需求之一。 而选择适合的编程语言对于项目的成功开发至关重要。 本文将重点探讨Go编程语言适合哪些项目开发,以帮助读者在选择合适的编程语言时做出明智的决策。 Go 编程语言适合哪些项目开发? Go是由Google开发

    2024年02月04日
    浏览(80)
  • 深入解析 Go 语言中的 http.FileSystem

    本篇博文将深入研究 Go 语言中的 http.FileSystem 接口,这是在构建 Web 应用程序时至关重要的一部分。通过对 http.FileSystem 接口的深入探讨,我们将了解其基本原理、使用方法以及实际应用场景。 首先,我们将介绍 http.FileSystem 的基本概念和作用,以便读者对其有一个清晰的认识

    2024年03月19日
    浏览(38)
  • 【Golang | Gin】net/http和Gin起web服务时的简单对比

    Gin 是一个用 Go (Golang) 编写的 Web 框架,详细介绍参考官网:https://gin-gonic.com/zh-cn/docs/introduction/ 开始学习Gin之前,我们先首先回顾下使用net/http起一个简单的helloworld服务 注: 1、 http.HandleFunc : 使用一个默认的 DefaultServeMux 来注册路由信息。 / 是一个 pattern , greet 是一个 ha

    2024年02月08日
    浏览(45)
  • 100天精通Golang(基础入门篇)——第12天:深入解析Go语言中的集合(Map)及常用函数应用

    🌷 博主 libin9iOak带您 Go to Golang Language.✨ 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批

    2024年02月12日
    浏览(50)
  • golang 通用的 grpc http 基础开发框架

    golang 通用的 grpc http 基础开发框架 仓库地址: https://github.com/webws/go-moda 仓库一直在更新,欢迎大家吐槽和指点 transport: 集成 http(echo、gin)和 grpc。 tracing: openTelemetry 实现微务链路追踪 pprof: 分析性能 config: 通用的配置文件读取模块,支持 toml、yaml 和 json 格式。 logger: 日志系统

    2024年02月10日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包