当前位置: 首页 > news >正文

http包详解

http包的作用及使用

go的http包是go的web编程的核心内容,go的web框架本质上都是基于http提供的组件进行再度封装。我们来看一下http基本的使用:

func main() {http.Handle("/get", GetVal())http.Handle("/hello", Hello())http.Handle("/demo", http.HandlerFunc(Demo))if err := http.ListenAndServe("0.0.0.0:9191", nil); err != nil {fmt.Println("err: %v", err)}
}func GetVal() http.HandlerFunc {return func(w http.ResponseWriter, r *http.Request) {val := "get\n"fmt.Fprintf(w, val)}
}func Hello() http.HandlerFunc {return func(w http.ResponseWriter, r *http.Request) {val := "hello\n"w.Write([]byte(val))}
}func Demo(w http.ResponseWriter, r *http.Request) {val := "get\n"fmt.Fprintf(w, val)
}

代码非常简单,就是为路由注册一个handler来处理请求并写入响应,我们来探究一下它的内部是如何实现的

源码分析

http包下的重要数据结构

ServerMux

type ServeMux struct {mu       sync.RWMutex //保证读写路由表的并发安全m         map[string]muxEntry 
}

它是http包中的路由器组件,存储路由及handler的信息,能够通过路由规则快速匹配到对应的handler(高版本go使用的前缀树方式,低版本使用map的方式).

muxEntry

type muxEntry struct {explict  boolhandler Handler
}

Handler

type Handler interface {ServeHTTP(ResponseWriter, *Request)
}

请求处理的业务逻辑函数,由用户自己定义,通过ServeHttp方法进行处理

HandlerFunc

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

它完全是为了方便用户使用,通过定义函数的方法替代定义结构体来注册handler

http包的工作流程——使用默认路由

注册路由

func Handle(pattern string, handler Handler) {DefaultServeMux.register(pattern, handler)
}//DefaultServeMux
func (mux *ServeMux) register(pattern string, handler Handler) {if err := mux.registerErr(pattern, handler); err != nil {panic(err)}
}func (mux *ServeMux) registerErr(patstr string, handler Handler) error {if patstr == "" {return errors.New("http: invalid pattern")}if handler == nil {return errors.New("http: nil handler")}if f, ok := handler.(HandlerFunc); ok && f == nil {return errors.New("http: nil handler")}pat, err := parsePattern(patstr)if err != nil {return fmt.Errorf("parsing %q: %w", patstr, err)}// Get the caller's location, for better conflict error messages.// Skip register and whatever calls it._, file, line, ok := runtime.Caller(3)if !ok {pat.loc = "unknown location"} else {pat.loc = fmt.Sprintf("%s:%d", file, line)}mux.mu.Lock()defer mux.mu.Unlock()// Check for conflict.if err := mux.index.possiblyConflictingPatterns(pat, func(pat2 *pattern) error {if pat.conflictsWith(pat2) {d := describeConflict(pat, pat2)return fmt.Errorf("pattern %q (registered at %s) conflicts with pattern %q (registered at %s):\n%s",pat, pat.loc, pat2, pat2.loc, d)}return nil}); err != nil {return err}mux.tree.addPattern(pat, handler)mux.index.addPattern(pat)mux.patterns = append(mux.patterns, pat)return nil
}

简单来说,但直接执行http.Handler方法注册路由时,就是将pattern及handler挂载到默认的ServeMux上。
DefaultServerMux会在挂载之前执行一系列的校验操作,并为了优化路由匹配性能引入一些复杂的数据结构和操作

server监听

入口-绑定port、监听请求

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

循环阻塞、等待请求、协程处理

简化版代码

func (srv *Server) Serve(l net.Listener) error {baseCtx := context.Background()if srv.BaseContext != nil {baseCtx = srv.BaseContext(origListener)if baseCtx == nil {panic("BaseContext returned a nil context")}}var tempDelay time.Duration // how long to sleep on accept failurectx := context.WithValue(baseCtx, ServerContextKey, srv)for {rw, err := l.Accept()c := srv.newConn(rw)c.setState(c.rwc, StateNew, runHooks) // before Serve can returngo c.serve(connCtx)}
}

server会启动一个协程不断接收新来的请求,并新开一个协程处理请求来提高go的并发性和性能

请求处理逻辑

func (c *conn) serve(ctx context.Context) {//根据不同的配置往ctx注入信息// 针对不同的err信息进行处理//for循环不断读取conn的信息——针对长链接for {w, err := c.readRequest(ctx)//处理w和err,可能会推出循环serverHandler{c.server}.ServeHTTP(w, w.req) //处理请求//判断是否服用连接,不复用则退出循环}
}
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {handler := sh.srv.Handlerif handler == nil {handler = DefaultServeMux}if !sh.srv.DisableGeneralOptionsHandler && req.RequestURI == "*" && req.Method == "OPTIONS" {handler = globalOptionsHandler{}}handler.ServeHTTP(rw, req)
}

如果传进来的handler为空则使用我们之前说的defaultServerMux,否则使用我们自己的路由器处理请求

相关文章:

http包详解

http包的作用及使用 go的http包是go的web编程的核心内容,go的web框架本质上都是基于http提供的组件进行再度封装。我们来看一下http基本的使用: func main() {http.Handle("/get", GetVal())http.Handle("/hello", Hello())http.H…...

Reqable实战系列:Flutter移动应用抓包调试教程

Flutter应用网络请求调试一直是业内难题,原因在于Dart语言标准库的网络请求不会走Wi-Fi代理,常规通过配置Wi-Fi代理来抓包的方式行不通。这给我们日常开发测试造成了很大的阻碍,严重降低工作效率。因此写一篇教程,讲解如何使用Req…...

乾元通渠道商中标吴忠市自然灾害应急能力提升项目

近日,乾元通渠道商中标宁夏回族自治区吴忠市自然灾害应急能力提升项目,乾元通作为设备厂家,为项目提供通信指挥类装备(多链路聚合设备)QYT-X1。 青岛乾元通数码科技有限公司作为国家应急产业企业,深耕于数据…...

护网蓝队面试

一、sql注入分类 **原理:**没有对用户输入项进行验证和处理直接拼接到查询语句中 查询语句中插⼊恶意SQL代码传递后台sql服务器分析执行 **从注入参数类型分:**数字型注入、字符型注入 **从注入效果分:**报错注入、布尔注入、延时注入、联…...

【高考志愿】金融学

目录 一、金融学类专业概述 二、主要课程 三、就业前景与方向 四、适合人群 五、金融学学科排名 六、总结 高考志愿选择金融学,无疑是一个既充满挑战又极具前景的决策。金融学,作为经济学门类下的重要分支,不仅涵盖了广泛的金融领域知识…...

返利App的用户行为分析与数据驱动决策

返利App的用户行为分析与数据驱动决策 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨返利App中的用户行为分析与数据驱动决策的技术细节和实…...

python基础:高级数据类型:集合

1、集合的定义 集合是一个无序且无重复元素的列表。其定义与数学定义一致。其无序和不重复和字典特征类似,但是无“值”。 2、集合的创建 集合一般由列表创建,在初始化列表时保证其元素唯一性,即为集合。 创建方法:x set(list…...

idk17配置

只需要把zip包解压,然后配置环境变量: bin目录路径粘到path里面就好了 然后打开cmd窗口分别输入 java javac java -version 验证...

Java实现日志全链路追踪.精确到一次请求的全部流程

广大程序员在排除线上问题时,会经常遇见各种BUG.处理这些BUG的时候日志就格外的重要.只有完善的日志才能快速有效的定位问题.为了提高BUG处理效率.我决定在日志上面优化.实现每次请求有统一的id.通过id能获取当前接口的全链路流程走向. 实现效果如下: 一次查询即可找到所有关…...

你敢相信吗,AI绘画正在逐渐取代你的工作!

前言 在当今信息技术高速发展的时代,AI绘画技术的崛起已引起了广泛关注和讨论。许多人开始担心AI技术是否会逐渐取代传统绘画师的工作。人类无疑是感性的动物,创作出来的艺术作品常常带有浓郁的个人风格和情感。但AI绘画在某些方面的突破,使…...

博途PLC轴工艺对象随动误差监视功能

S7-1200PLC和V90总线伺服通过工艺对象实现定位控制时在组态工艺对象里有这样的随动误差监视功能介绍,关于这个功能,今天我们解读下,工艺对象组态编程可以参考下面文章链接: S7-1200PLC和V90总线伺服通过工艺对象实现定位控制(标准报文3应用)_v90工艺对象3号报文-CSDN博客文…...

《昇思25天学习打卡营第24天 | 昇思MindSporeResNet50图像分类》

24天 本节学习了使用ResNet50网络对CIFAR-10数据集进行分类。 步骤: 1.数据集准备与加载 2.构建网络 残差网络结构(Residual Network)是ResNet网络的主要亮点,ResNet使用残差网络结构后可有效地减轻退化问题,实现更深的网络结构设计&#x…...

糟糕的管理者都有这几个特征

在我们的职业生涯中,我们都期望能遇到一位英明睿智、引领团队走向辉煌的管理者。然而,现实往往并非总是如此美好,总会有一些管理能力差的人混迹其中,给团队带来诸多困扰。今天,我们就来看看糟糕的管理者身上都有哪些特…...

Python (Ansbile)脚本高效批量管理服务器和安全

1、简介 在现代 IT 基础设施中,管理大量服务器是一项复杂而繁琐的任务。特别是在检查服务器的存活状态以及 SSH 登录等任务上,手动操作非常耗时且容易出错。本文将介绍如何使用 Python 脚本实现对多台服务器的批量检查和管理,包括检查服务器…...

《数字图像处理与机器视觉》案例三 (基于数字图像处理的物料堆积角快速测量)

一、前言 物料堆积角是反映物料特性的重要参数,传统的测量方法将物料自然堆积,测量物料形成的圆锥表面与水平面的夹角即可,该方法检测效率低。随着数字成像设备的推广和应用,应用数字图像处理可以更准确更迅速地进行堆积角测量。 …...

Postman接口测试工具的原理及应用详解(四)

本系列文章简介: 在当今软件开发的世界中,接口测试作为保证软件质量的重要一环,其重要性不言而喻。随着前后端分离开发模式的普及,接口测试已成为连接前后端开发的桥梁,确保前后端之间的数据交互准确无误。在这样的背景…...

扛鼎中国AI搜索,天工凭什么?

人类的创作不会没有瓶颈,但AI的热度可不会消停。 大模型之战依旧精彩,OpenAI选择在Google前一天举行发布会,两家AI企业之间的拉扯赚足了热度。 反观国内,百模大战激发了大家对于科技变革的热切期盼,而如今行业已逐渐…...

【Ant Design Vue的更新日志】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...

Elasticsearch环境搭建|ES单机|ES单节点模式启动|ES集群搭建|ES集群环境搭建

文章目录 版本选择单机ES安装与配置创建非root用户导入安装包安装包解压配置JDK环境变量配置single-node配置JVM参数后台启动|启动日志查看启动成功,访问终端访问浏览器访问 Kibana安装修改配置后台启动|启动日志查看浏览器访问 ES三节点集群搭建停止es服务域名配置…...

System.currentTimeMillis() JAVA 转C#

JAVA中的System.currentTimeMillis() ,指获取当前时间与1970年1月1日00:00:00 GMT之间所差的毫秒数的方法。 这个方法返回的是一个long类型的值,表示从某个固定时间点(通常是UNIX纪元,即1970年1月1日00:00:00 GMT)到…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​,覆盖应用全生命周期测试需求,主要提供五大核心能力: ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

基于服务器使用 apt 安装、配置 Nginx

🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...