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

Go第三方框架--gin框架(一)

序言

Gin框架作为go语言使用最多的web框架,以其快速的响应速度和对复杂http路由配置的支持受到程序员和媛们的喜爱,几乎统治了web市场。但作为一名合格的程序员,要知其然更要知其所以然,不然八股文背的也没有啥意思。本着这个原则鄙人打算站在前人的大腿根上从头到尾梳理下Gin的执行流程,主要涉及两大部分:1. 服务器的建立(重点是:Gin是怎么处理和存储各种不同的路由路径和请求函数体的);2. 客户端的连接(主要涉及根据路由寻找对应函数体来执行具体业务逻辑)

1. gn框架的诞生

1.1 go 原生web框架

go 原生的 web框架 在 net/http 包里,因不是本文重点,所以只简要介绍。
net/http 主要采用 map的原理来 存储 路径和handler 其中 key 是 路径 value 是 handler ,如下图的代码

# ServeMux是一个HTTP请求多路复用器。其中 m 保存了 其请求路径和handler的映射关系。
type ServeMux struct {mu    sync.RWMutexm     map[string]muxEntryes    []muxEntry // slice of entries sorted from longest to shortest.hosts bool       // whether any patterns contain hostnames
}
type muxEntry struct {h       Handlerpattern string
}
func TestHttp(t *testing.T) {// 创建路由器mux := http.NewServeMux()// 设置路由规则mux.HandleFunc("/hello", hello)mux.HandleFunc("/hello/hell", hello2)mux.HandleFunc("/hel/ww", hello2)mux.HandleFunc("/helw/*ww", hello2)// 创建服务器server := &http.Server{Addr:         Addr,WriteTimeout: time.Second * 3, //超时时间Handler:      mux,             //路由规则  }// 监听端口并提供服务log.Println("Starting httpserver at " + Addr)err := server.ListenAndServe()if err != nil {panic(err)return}log.Fatal()
}func hello(w http.ResponseWriter, r *http.Request) {time.Sleep(1 * time.Second)w.Write([]byte("bye bye ,this is httpServer"))
}func hello2(w http.ResponseWriter, r *http.Request) {time.Sleep(1 * time.Second)w.Write([]byte("bye bye ,this is httpServer"))
}

其 建立的 map如下:
在这里插入图片描述
可以看出其确实建立了一个 map来存储 路径和handler的映射关系。采用map形式 查找的速度也比较的块。但是为啥还要采用Gin框架呢。
我们来简要梳理下我们程序员在工作过程中需要啥样的web框架吧

  1. 需要一个可以处理通配符的框架,比如这种: aa/dd* 虽然我(net/http)不支持但是我 速度快啊
  2. 需要可以处理中间件的框架 比如 对日志的处理等 虽然我(net/http)不支持但是我 速度快啊
  3. 需要 支持分组的框架 比如 v1 v2这种不同的版本 虽然我(net/http)不支持但是我 速度快啊

目前看来 net/http不适合这种复杂场景的业务逻辑 当然 Google go开发组 目的只是提供一个简小的web框架,设计目标是简单和通用。go开发组 当然也想到了 要利用开源的优势为各路大神提供大显神通的机会。问题是怎么接入呢,现实世界和虚拟世界的连接入口是 二维码。那gin框架如何接入 net/http 呢,也就是如何在重新利用它的其他功能的情况下,再进行扩展呢 你当然能想到了 这就是 interface 接口。

net/http框架中 确实是 通过实现接口来 进行 路由查找 并找到要执行的 hanlder(例如 上述代码中的hello),这样路由建立模块和路由寻址查找handler模块就可以通过不同实现来形成不同的第三方框架。建立路由模块是第三方包独自完成,而路由寻址查找模块主要是实现了 如下接口:

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

这样第三方框架 就可以复用net/http 的大部分功能(包括最重要的 epoll多路复用),并通过实现 ServeHTTP 接口 来实现自己的 路由查找模块(ps: 路由建立模块需自己建立 这块功能用不到接口) ,说完了 理论 那我们再来梳理下 net/http 从 建立连接 到 ServeHTTP的调用链,来验证下上述是否是这样的。

1.2 原生 net/http的 调用链

以 TestHttp 这个函数为例,调用入口是 server.ListenAndServe() ,其调用链为

在这里插入图片描述
可以看到 其最终调用到了 ServeHTTP() 这个函数,而所有第三方框架都是实现了 这个函数。这个函数包括 根据req函数中的 url获取 handler(第三方框架提供) 、处理handler和对客户端返回结果三大块的功能。
这样第三方框架就可以 实现ServeHTTP这个函数来 实现对 handler的获取(怎么建立路由结构是第三方框架自己定义)。

1.3 gin等第三方web框架和net/http关系

让我们脱离源码 来梳理下
在这里插入图片描述
可以看到 第三方 框架 主要是头尾两个地方跟 net/http不同 中间还是需要复用net/http代码。后续 讲解会围绕这张流程图展开,其中比较重要的是 圆圈 1、2和3,1 包括 gin 的引擎 engine 其包括建立压缩前缀树的功能并实现了 serverHttp接口 形成了 3,2主要涉及了多路复用技术。
以下的 步骤 2、3、4主要涉及圆圈1 的内容,步骤5 涉及圆圈2 的内容 ,步骤6 涉及圆圈3的内容

2. gin框架简介

2.1 gin框架发展历程

gin 框架早期版本是基于julienschmidt/httprouter 发展而来,julienschmidt/httprouter是一个高性能的http请求器。但是随着gin框架的发展 它逐渐发展出了自己的 路由实现器,实现源码也部分参考 julienschmidt/httprouter 这也就是为什么好多资料都说 gin基于julienschmidt/httprouter 但是你去看它最新的源码却没发现针对 julienschmidt/httprouter的引用。
gin框架之所以运行效率高是因为采用了一种叫 Radix Tree (压缩前缀树)的结构体来存储路由路径,其是一种例如有如下路由:

/aa/bb
/aa/bd
/aa/cc
/ac/dd
/ee/ff

建立压缩前缀树 ,请思考下其建立的树是左边还是右边呢
在这里插入图片描述
gin 框架的路由树的建立 就是一步一步建立如上图所示的 压缩前缀树 ps:真是的树的节点比较复杂 但是大体步骤就是如此
那么压缩前缀树 有啥优点呢 gin 为什么使用这种结构来存储器节点呢 直觉上看 我们可以想到两点 1: 这种树形结构 查找的时间复杂度是时间复杂度为 o(k) ,k是字符串的长度 2: 压缩证明其使用的空间比较少 可以看到 路径中 有 6个a 但是 我们树节点中只有 2个。这只是我们直观看出来的,对不对呢,是否还有其他优点呢?

答案: 对,当然有其他优点,这种树 也可以用来 进行通配符的匹配 例如这种 /aa/bb/* ;还可以快速建立路由分组等。这两种优势不是本文的重点,感兴趣的同学可以自行查阅资料。
既然你说gin 路由使用的是 压缩前缀树,口说无凭 我们来验证下吧 顺便看下建立的是左边还是右边的压缩前缀树

2.2 gin框架的使用

下面示例代码为(本文后续围绕下面例子展开代码讲解):

func TestGin(t *testing.T) {// 创建一个默认的路由引擎r := gin.Default()// 当客户端以GET方法请求路径时,会执行后面的匿名函数r.GET("/aa/bb", func(c *gin.Context) { c.JSON(200, gin.H{"route path ": "/aa/bb",}) })r.GET("/aa/bd", func(c *gin.Context) { c.JSON(200, gin.H{"route path ": "/aa/bd",}) })r.GET("/aa/cc", func(c *gin.Context) { c.JSON(200, gin.H{"route path ": "/aa/cc",}) })r.GET("/ac/dd", func(c *gin.Context) { c.JSON(200, gin.H{"route path ": "/ac/dd",}) })r.GET("/ee/ff", func(c *gin.Context) { c.JSON(200, gin.H{"route path ": "/ee/ff",}) })// 以上操作 **主要 涉及 圆圈 1**// 启动HTTP服务,默认在0.0.0.0:8080启动服务  **涉及 net/http 框架处理主逻辑 内部 主要 调用 net/http 包**r.Run()}

对上述代码 debugger 可以得到 r 这个参数的 实例 实力分析如下 其中 压缩前缀树的节点node结构体的结构如下:

type node struct {path      stringindices   stringwildChild boolnType     nodeTypepriority  uint32children  []*node // child nodes, at most 1 :param style node at the end of the arrayhandlers  HandlersChainfullPath  string
}

现在只需关注node节点的 path 和 children 这两个参数 node结构体详情会在后续步骤介绍
2.2.1 父节点
在这里插入图片描述
可以看到 父节点 path == “/” 且有两个孩子节点

2.2.2 第二层节点

在这里插入图片描述
可以看到 第二层 节点 左边节点 path==“a” 孩子个数为2 ;右边节点 pah 是 “ee/ff” 这里就是将节点进行了压缩 ee 和 ff 不用再拆分了。因为 ff是ee的唯一的一个孩子节点 因为寻址路径唯一 所以可以向上合并,以便节省空间。

2.2.3 第三层节点

在这里插入图片描述
可以看到 左边节点 path==“a/” 孩子节点个数为2 ;右边节点 path==“c/dd”(压缩了) 孩子节点为空

2.2.4 第四层节点
在这里插入图片描述
可以看到 左边 节点 path=“b” ,其有两个孩子节点;右边节点 path=“cc” 其没有孩子节点

2.2.5 第五层 节点

在这里插入图片描述
可以看到 左边节点 path==“b” 无孩子节点 ;右边节点 path==“d” 无孩子节点

到这里我们可以看出来其确实是建立了一颗 压缩前缀树。总结下来就是: 1. 孩子节点必须大于1(否则应向上合并)2: 压缩有两层含义 第一层将 路由里面 重复的路径 进行压缩 例如 字母a 压缩后就剩2个;第二层 一个节点有一个子节点时 向上兼并 压缩空间
所以建立的前缀树是 右边的。

r.run()执行后 在浏览器输入 路径 就可以看到 对应的函数被执行(注意:默认端口是8080)结果 如图 这边主要涉及 圆圈 2–>3
在这里插入图片描述

2.3 gin框架的执行过程

梳理完毕 压缩前缀树的建立 那现在开始我们梳理下 整个 gin框架的流程图 其实主要是围绕 构建的压缩前缀树展开的 ,我个人比较愿意先学习框架使用,然后再进入细节,这样有一个提纲挈领的抓手,我们就知道这些细节在整体脉络中的位置,不至于陷进去失去了方向感。

通过1.3的图可以看到 gin 框架 大概 分为 三大部分

  1. 创建 压缩前缀树 并且 将 路由 对应的节点 按照规则 插入树节点 ---- 步骤一(圆圈1)
  2. 运行 引擎 建立 对tcp套接字的监听 这里采用多路复用技术 进行阻塞 等待链接到来 ---- 步骤二
  3. 浏览器 输入 url 进行客户端请求 这时 唤醒阻塞的程序 从圆圈2 按照箭头执行顺序 一直执行到 圆圈3,然后在圆圈3 中遍历 压缩前缀树 找到对应的 handler (对于路径 :/aa/bd 其 handler 为:func(c *gin.Context) { c.JSON(200, gin.H{"route path ": “/aa/bd”}) }) 执行后 返回结果 ---- 步骤三

3. gn框架源码–四种重要的结构体

框架一般都会采用面向对象的方式来构建,而面向对象中最重要的核心就是结构体。gin框架四种重要的结构体 分别是 Engine/RouterGroup/Node/context ,其中Engine 包含了 RouteGroup和Node 是gin框架的引擎结构体 ;Node是压缩前缀树的树节点,用来保存 压缩路径和handler,在2.2.1----2.2.5中已经做过简要介绍 ;Context 结构体官方介绍是 gin最重要的结构体 ,它允许我们在中间件之间传递变量,管理流,处理 request 请求体和 respose 响应体。可以说 gin 框架基本上是围绕着这四个结构体来操作的。

3.1 Engine 结构体
type Engine struct {RouterGroup   // 路由组 ...... //  这里为了使得文章简短 一些本文讲解没用到的 属性 没有列举 感兴趣的可以自己研究下 // UseH2C enable h2c support.UseH2C bool// ContextWithFallback enable fallback Context.Deadline(), Context.Done(), Context.Err() and Context.Value() when Context.Request.Context() is not nil.ContextWithFallback booldelims           render.DelimssecureJSONPrefix stringHTMLRender       render.HTMLRenderFuncMap          template.FuncMapallNoRoute       HandlersChainallNoMethod      HandlersChainnoRoute          HandlersChainnoMethod         HandlersChainpool             sync.Pool   // 这个池化技术 用来存储 Context结构体。 它是 gin框架很重要的结构体 主要用来 处理 request和 respose 请求trees            methodTrees   // 方法树 针对 Get/Post/Delete 等不同请求 都生成一个树 9种请求 9种树 但实现原理都是相同的 本文只介绍 Get方法,其 包含了 Node 结构体maxParams        uint16maxSections      uint16trustedProxies   []stringtrustedCIDRs     []*net.IPNet
}

Engine 结构体 是 gin 框架的入口,其包含了许多属性 但对于 我们学习jin框架核心执行逻辑来说,只需要知道 RouterGroup/pool/trees 这三个就行了

3.2 RouteGroup结构体
type RouterGroup struct {Handlers HandlersChain   // 需要处理的 handler 链,一般是 默认hanlder(例如 处理 logger和panic的handlewr)+ group组的中间件handler(例如 鉴权等)+ 用户 注册的 handlerbasePath string  // 组的基本路径engine   *Engine // gin 框架 引擎root     bool // 跟节点
}

RouterGroup 主要是用来 对路由进行操作的,包括对post/get等方法的处理。

3.3 Node 结构体
type node struct {path      string  // 节点路劲indices   string // 其子节点的 path的第一个单词 组成的 字符串 用来快速定位路径寻址时 是否走此孩子节点wildChild boolnType     nodeType // 节点类型priority  uint32  // 优先级 从左往右 越左侧 优先级越大 优先从左边开始 说明 左边的 重复的路径前缀比较多 同层其优先级越高 子节点越多 ,一般情况下 priority等于其直属孩子节点个数,且如果其直属孩子节点为一个 或者 为空,其 优先级 为 1children  []*node // child nodes, at most 1 :param style node at the end of the arrayhandlers  HandlersChain  // 处理器 存储 节点 handler 链 fullPath  string // 全路径 fullPath 
}

node 是压缩前缀树子节点,是gin框架之所以速度快的核心原因,也是我们本篇文章重点需要介绍和理解的结构体。
对于节点属性的理解 可以对照着 标题 2.21----2.2.5来理解

3.4 context 结构体
type Context struct {writermem responseWriterRequest   *http.RequestWriter    ResponseWriterParams   Paramshandlers HandlersChainindex    int8fullPath stringengine       *Engineparams       *ParamsskippedNodes *[]skippedNode// This mutex protects Keys map.mu sync.RWMutex// Keys is a key/value pair exclusively for the context of each request.Keys map[string]any// Errors is a list of errors attached to all the handlers/middlewares who used this context.Errors errorMsgs// Accepted defines a list of manually accepted formats for content negotiation.Accepted []string// queryCache caches the query result from c.Request.URL.Query().queryCache url.Values// formCache caches c.Request.PostForm, which contains the parsed form data from POST, PATCH,// or PUT body parameters.formCache url.Values// SameSite allows a server to define a cookie attribute making it impossible for// the browser to send this cookie along with cross-site requests.sameSite http.SameSite
}

context 是gin框架最重要的结构体 其包含了对 请求 和 响应的 处理逻辑,可以在中间件之间传递数据流。因不是本文的理解gin框架的需要用到的结构体,暂不做过多介绍,请自行用谷歌百度一下。

相关文章:

Go第三方框架--gin框架(一)

序言 Gin框架作为go语言使用最多的web框架,以其快速的响应速度和对复杂http路由配置的支持受到程序员和媛们的喜爱,几乎统治了web市场。但作为一名合格的程序员,要知其然更要知其所以然,不然八股文背的也没有啥意思。本着这个原则…...

网络安全——笔记

XSS:跨站脚本(Cross-site scripting) XSS 全称“跨站脚本”,是注入攻击的一种。其特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文…...

Maven pom.xml配置详解

pom.xml是什么&#xff1f; pom.xml&#xff08;项目对象模型-Project Object Model的缩写&#xff09;是Maven项目的核心配置文件&#xff0c;用于管理项目的依赖、插件、构建配置等。 举例说明&#xff1a;以阿里巴巴的fastjson为例&#xff1a; <?xml version"1.…...

2024深圳国际电线电缆及电源产品展览会

2024深圳国际电线电缆及电源产品展览会 2024 Shenzhen International Coupling, Clutch and Brake Exhibition 时间&#xff1a;2024年08月28-30日 地点&#xff1a;深圳国际会展中心&#xff08;新馆&#xff09; 预订以上展会详询陆先生 I38&#xff08;前三位&#xff…...

如何成功将自己开发的APP上架到应用商店

随着移动应用市场的蓬勃发展&#xff0c;开发一款优秀的APP已成为许多企业和个人的首要选择。然而&#xff0c;成功上架并有效推广APP至关重要。本文将逐步介绍完整的上架流程&#xff0c;包括准备所需材料、注册开发者账户、进行APP备案、提交审核以及上架成功后的推广和维护。…...

Jetson AGX ORIN 配置 FGVC-PIM 神经网络(包含 arm64 下面 torch 和 torchvision 配置内容)

Jetson AGX ORIN 配置 FGVC-PIM 神经网络 文章目录 Jetson AGX ORIN 配置 FGVC-PIM 神经网络配置 ORIN 环境创建 FGVC-PIM 虚拟环境安装 PyTorch安装 torchvision安装其他依赖包 配置 ORIN 环境 首先先配置 ORIN 的环境&#xff0c;可以参考这个链接&#xff1a; Jetson AGX …...

mybatisplus和mybatis兼容问题

Invalid bound statement (not found) 错误 原xml配置 <bean id"sqlSessionFactory" class"org.mybatis.spring.SqlSessionFactoryBean"><property name"mapperLocations" value"classpath:/META-INF/mapper/*.xml"/>&l…...

nodejs安装使用React

1、react安装 首先&#xff0c;确保电脑上具备nodejs环境&#xff0c;之后用 winr 呼出控制台&#xff0c;输入 cmd 命令弹出cmd控制台&#xff08;小黑框&#xff09;之后在默认路径输入如下代码 npm i -g create-react-app //全局安装react环境无需选择特定文件夹安装成功后…...

防御性编程,可能是导致被裁员的更大的原因,别被误导了

裁员与反裁员是当前IT界一个经典的话题&#xff0c;作为打工者的猿人常常讨论了N多的防御性编程&#xff0c;代码不可读、代码不好改、代码深度嵌套、代码留bug等等。 其实防御性编程只会让决策者加速解耦你与业务系统&#xff1a; 1、增加代码走查的环节&#xff08;增加成本…...

Unity与鼠标相关的事件(自己记忆用)

1. OnMouseDown&#xff1a;当用户按下鼠标按钮时调用。 - 参数&#xff1a;MouseEvent&#xff0c;可以用来确定哪个鼠标按钮被按下。 2. OnMouseUp&#xff1a;当用户释放鼠标按钮时调用。 - 参数&#xff1a;MouseEvent&#xff0c;可以用来确定哪个鼠标按钮被释放。…...

模型权重下载方法

下载方法1&#xff1a;git lfs下载 1、在hf-mirror.com中搜索模型&#xff0c;如搜索text2vec-large-chinese&#xff0c; 点击模型进入页面&#xff1a;https://hf-mirror.com/GanymedeNil/text2vec-large-chinese/tree/main 2、git lfs install 3、git clone https://hf-mir…...

JS基础之 数据浅拷贝与深拷贝

一、拷贝背景 JS引用数据类型有两类&#xff1a;基本数据类型和引用数据类型&#xff1b; 基本类型&#xff1a;String&#xff0c;Number&#xff0c;Boolean&#xff0c;Null&#xff0c;Undefined&#xff0c;symbol这6种基本数据类型它们是直接按值存放的&#xff0c;所以…...

FFmpeg开发笔记(十四)音频重采样的缓存

FFmpeg在很多地方都运用了缓存机制&#xff0c;比如《FFmpeg开发实战&#xff1a;从零基础到短视频上线》一书的“3.3.2 对视频流重新编码”介绍了编解码的数据缓存&#xff0c;不单是视频编码过程和视频解码过程有缓存&#xff0c;甚至连音频重采样都用到了缓存。 也就是说&a…...

详解Python面向对象编程(一)

类和对象 面向过程——怎么做&#xff1f; &#xff08;1&#xff09;把完成某一需求的所有步骤、从头到尾&#xff0c;逐步实现 &#xff08;2&#xff09;根据开发需求&#xff0c;将某些功能独立的代码块封装成一个又一个的函数 &#xff08;3&#xff09;最后完成的代码&a…...

一文带你完整了解Go语言IO基础库

作者 | 百度小程序团队 导读 introduction 对于刚接触Golang学习的同学&#xff0c;估计比较难掌握的知识点之一就是文件IO处理&#xff0c;光在基础库里会发现 golang除了io包提供文件处理外&#xff0c;os包&#xff0c;http包&#xff0c;embed包都有提供类似的处理&#xf…...

Java基于微信小程序的校园请假系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#…...

Expert Prompting-引导LLM成为杰出专家

ExpertPrompting: Instructing Large Language Models to be Distinguished Experts 如果适当设计提示&#xff0c;对齐的大型语言模型&#xff08;LLM&#xff09;的回答质量可以显著提高。在本文中&#xff0c;我们提出了ExpertPrompting&#xff0c;以激发LLM作为杰出专家回…...

Element-Plus下拉菜单边框去除教程

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…...

免费redis可视化工具windows/mac都可以使用,开源免费

官方地址&#xff1a;RedisInsight | The Best Redis GUI github开源地址&#xff1a;GitHub - RedisInsight/RedisDesktopManager Redis Desktop Manager – Redis可视化管理工具、redis图形化管理工具、redis可视化客户端、redis集群管理工具。 官方下载方式 滚动到页面底…...

PHPCMS v9城市分站插件

PHPCMS自带的有多站点功能&#xff0c;但是用过的朋友都知道&#xff0c;自带的多站点功能有很多的不方便之处&#xff0c;例如站点栏目没法公用&#xff0c;每个站点都需要创建模型、每个站点都需要单独添加内容&#xff0c;还有站点必须静态化。如果你内容很多这些功能当然无…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)

cd /home 进入home盘 安装虚拟环境&#xff1a; 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境&#xff1a; virtualenv myenv 3、激活虚拟环境&#xff08;激活环境可以在当前环境下安装包&#xff09; source myenv/bin/activate 此时&#xff0c;终端…...

C++_哈希表

本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、基础概念 1. 哈希核心思想&#xff1a; 哈希函数的作用&#xff1a;通过此函数建立一个Key与存储位置之间的映射关系。理想目标&#xff1a;实现…...

Linux中INADDR_ANY详解

在Linux网络编程中&#xff0c;INADDR_ANY 是一个特殊的IPv4地址常量&#xff08;定义在 <netinet/in.h> 头文件中&#xff09;&#xff0c;用于表示绑定到所有可用网络接口的地址。它是服务器程序中的常见用法&#xff0c;允许套接字监听所有本地IP地址上的连接请求。 关…...