golang 引入swagger(iris、gin)

golang 引入swagger(iris、gin)

在开发过程中,我们不免需要调试我们的接口,但是有些接口测试工具无法根据我们的接口变化而动态变化。文档和代码是分离的。总是出现文档和代码不同步的情况。这个时候就可以在我们项目中引入swagger,方便后期维护以及他人快速上手项目

0 下载swagger

# 1 安装swagger
# 在go.mod目录所在位置执行命令
go get -u github.com/swaggo/swag/cmd/swag

# 查看是否安装成功
swag -v

# 如果发现报错:zsh: command not found: swag,则需要手动编译生成swag
cd $GOPATH/pkg/mod/github.com/swaggo/swag@v1.16.2/cmd/swag/
sudo go build
sudo mv swag $GOPATH/bin
# 查看是否安装成功
swag -v 

在这里插入图片描述

1 iris引入swagger

①导入iris-contrib/swagger依赖

//安装swagger扩展,本项目使用的是iris最新版(iris/v12),因此需要安装iris-swagger/v12扩展

go get -v "github.com/iris-contrib/swagger/swaggerFiles"
go get -v "github.com/iris-contrib/swagger/v12"

②添加对应swagger注解 & swag init生成docs

在项目对应文件添加swagger注解,并通过swag init生成docs
注意:如果代码中的swagger注释有修改,需要重新执行swag init生成文档

例如:我给controller添加注解:

package controller

import (
    "encoding/json"
    "github.com/kataras/iris/v12"
    "github.com/kataras/iris/v12/mvc"
    "myTest/demo_home/swagger_demo/iris/model"
    "net/http"
)

type UserController struct {
    Ctx iris.Context
}

func (u *UserController) BeforeActivation(b mvc.BeforeActivation) {
    b.Handle(http.MethodGet, "/getAll", "GetAllUsers")
}

// GetAllUsers @Summary 获取用户信息
// @Description 获取所有用户信息
// @Tags 用户
// @Accept json
// @Produce json
// @Router /user/getAll [get]
func (u *UserController) GetAllUsers() mvc.Result {
    //手动模拟从数据库查询到user信息
    resp := new(mvc.Response)
    resp.ContentType = "application/json"
    user1 := new(model.User)
    user1.Name = "zhangsan"
    user1.Age = 20
    user2 := new(model.User)
    user2.Name = "li4"
    user2.Age = 28
    users := []model.User{*user1, *user2}
    marshal, _ := json.Marshal(users)
    resp.Content = marshal
    resp.Code = http.StatusOK
    return resp
}
//在项目根目录执行swag init ( 默认会找当前目录下的 main.go 文件,如果不叫 main.go 也可以-g手动指定文件位置。)
swag init # swag init -g cmd/api/api.go -o cmd/api/docs (-o指定docs生成位置)

③main.go中引入swag生成doc包

在 main.go 中导入刚才生成的 docs 包

package main

import (
	"github.com/iris-contrib/swagger/v12"
	"github.com/iris-contrib/swagger/v12/swaggerFiles"
	"github.com/kataras/iris/v12"
	"myTest/demo_home/swagger_demo/iris/controller"
	_ "myTest/demo_home/swagger_demo/iris/docs" //引入docs包
)

func main() {
	app := iris.New()
	controller.InitControllers(app)
	config := &swagger.Config{
		URL: "http://localhost:8080/swagger/doc.json", //The url pointing to API definition
	}
	app.Get("/swagger/{any}", swagger.CustomWrapHandler(config, swaggerFiles.Handler))
	app.Listen(":8080")
}

④运行程序访问ip:port/swagger/index.html页面

运行main.go,浏览器输入:http://localhost:8080/swagger/index.html

在这里插入图片描述

全部代码

Github:
https://github.com/ziyifast/ziyifast-code_instruction/tree/main/swagger_demo

项目结构:
在这里插入图片描述

main.go
package main

import (
    "github.com/iris-contrib/swagger/v12"
    "github.com/iris-contrib/swagger/v12/swaggerFiles"
    "github.com/kataras/iris/v12"
    "myTest/demo_home/swagger_demo/iris/controller"
    _ "myTest/demo_home/swagger_demo/iris/docs" # 引入生成的docs包
)

func main() {
    app := iris.New()
    controller.InitControllers(app)
    config := &swagger.Config{
       URL: "http://localhost:8080/swagger/doc.json", //The url pointing to API definition
    }
    app.Get("/swagger/{any}", swagger.CustomWrapHandler(config, swaggerFiles.Handler))
    app.Listen(":8080")
}
controller/controllers.go
package controller

import (
    "github.com/kataras/iris/v12"
    "github.com/kataras/iris/v12/mvc"
)

func InitControllers(app *iris.Application) {
    myMvc := mvc.New(app.Party("/user"))
    myMvc.Handle(new(UserController))
}
controller/user_controller.go
package controller

import (
    "encoding/json"
    "github.com/kataras/iris/v12"
    "github.com/kataras/iris/v12/mvc"
    "myTest/demo_home/swagger_demo/iris/model"
    "net/http"
)

type UserController struct {
    Ctx iris.Context
}

func (u *UserController) BeforeActivation(b mvc.BeforeActivation) {
    b.Handle(http.MethodGet, "/getAll", "GetAllUsers")
}

// GetAllUsers @Summary 获取用户信息
// @Description 获取所有用户信息
// @Tags 用户
// @Accept json
// @Produce json
// @Router /user/getAll [get]
func (u *UserController) GetAllUsers() mvc.Result {
    //手动模拟从数据库查询到user信息
    resp := new(mvc.Response)
    resp.ContentType = "application/json"
    user1 := new(model.User)
    user1.Name = "zhangsan"
    user1.Age = 20
    user2 := new(model.User)
    user2.Name = "li4"
    user2.Age = 28
    users := []model.User{*user1, *user2}
    marshal, _ := json.Marshal(users)
    resp.Content = marshal
    resp.Code = http.StatusOK
    return resp
}

2 gin引入swagger

①导入swaggo/gin-swagger依赖

// 引入gin及gin-swagger依赖
go get "github.com/gin-gonic/gin"
go get "github.com/swaggo/gin-swagger/swaggerFiles"
go get "github.com/swaggo/gin-swagger"

②添加对应swagger注解 & swag init生成docs

注意:如果代码中的swagger注释有修改,需要重新执行swag init生成文档
user_controller.go

package controller

import (
    ret "myTest/demo_home/swagger_demo/gin/response"
    "net/http"
    "strconv"
    "time"

    "github.com/gin-gonic/gin"
)

// Hello 测试
// @Summary      测试SayHello
// @Description  向你说Hello
// @Tags         测试
// @Accept       json
// @Produce      json
// @Param        who  query     string  true             "人名"
// @Success      200  {string}  string  "{"msg": "hello  lixd"}"
// @Failure      400  {string}  string  "{"msg": "who    are  you"}"
// @Router       /hello [get]
func Hello(c *gin.Context) {
    who := c.Query("who")
    if who == "" {
       c.JSON(http.StatusBadRequest, gin.H{"msg": "who are u?"})
       return
    }
    c.JSON(http.StatusOK, gin.H{"msg": "hello " + who})
}

type LoginReq struct {
    Username string `json:"username"`
    Password string `json:"password"`
}
type LoginResp struct {
    Token string `json:"token"`
}

// Login 登陆
// @Summary      登陆
// @Tags         登陆注册
// @Description  登入
// @Accept       json
// @Produce      json
// @Param        user  body      LoginReq                    true  "用户名密码"
// @Success      200   {object}  ret.Result{data=LoginResp}  "token"
// @Failure      400   {object}  ret.Result                  "错误提示"
// @Router       /login [post]
func Login(c *gin.Context) {
    var m LoginReq
    if err := c.ShouldBind(&m); err != nil {
       c.JSON(http.StatusBadRequest, ret.Fail("参数错误"))
       return
    }

    if m.Username == "admin" && m.Password == "123456" {
       resp := LoginResp{Token: strconv.Itoa(int(time.Now().Unix()))}
       c.JSON(http.StatusOK, ret.Success(resp))
       return
    }
    c.JSON(http.StatusUnauthorized, ret.Fail("user  or  password  error"))
}

③main.go中引入swag生成doc包

package main

import (
    "github.com/gin-gonic/gin"
    ginSwagger "github.com/swaggo/gin-swagger"
    "github.com/swaggo/gin-swagger/swaggerFiles"
    "myTest/demo_home/swagger_demo/gin/controller"
    _ "myTest/demo_home/swagger_demo/gin/docs"
)

var swagHandler gin.HandlerFunc

// @title           Swagger Example API
// @version         1.0
// @description     This is a sample server.
// @termsOfService  https://lixueduan.com

// @contact.name   lixd
// @contact.url    https://lixueduan.com
// @contact.email  xueduan.li@gmail.com

// @license.name  Apache 2.0
// @license.url   http://www.apache.org/licenses/LICENSE-2.0.html

// @host      localhost:8080
// @BasePath  /api/v1

// SwaggerUI: http://localhost:8080/swagger/index.html
func main() {
    e := gin.Default()
    v1 := e.Group("/api/v1")
    {
       v1.GET("/hello", controller.Hello)
       v1.POST("/login", controller.Login)
    }
    e.GET("swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
    if swagHandler != nil {
       e.GET("/swagger/*any", swagHandler)
    }

    if err := e.Run(":8080"); err != nil {
       panic(err)
    }
}

resp.go:

// Package ret 统一返回结构
package ret

import (
    "net/http"
)

const (
    MsgSuccess = "success"
    MsgFail    = "fail"
)

type Result struct {
    Code int         `json:"code"`
    Data interface{} `json:"data"`
    Msg  string      `json:"msg"`
}

func Success(data interface{}, msg ...string) *Result {
    var m = MsgSuccess
    if len(msg) > 0 {
       m = msg[0]
    }
    return &Result{
       Code: http.StatusOK,
       Data: data,
       Msg:  m,
    }
}

func Fail(msg ...string) *Result {
    var m = MsgFail
    if len(msg) > 0 {
       m = msg[0]
    }
    return &Result{
       Code: http.StatusBadRequest,
       Data: "",
       Msg:  m,
    }
}

④运行程序访问ip:port/swagger/index.html

http://localhost:8080/swagger/index.html

在这里插入图片描述

全部代码

地址:
https://github.com/ziyifast/ziyifast-code_instruction/tree/main/swagger_demo

main.go
package main

import (
	"github.com/gin-gonic/gin"
	ginSwagger "github.com/swaggo/gin-swagger"
	"github.com/swaggo/gin-swagger/swaggerFiles"
	"myTest/demo_home/swagger_demo/gin/controller"
	_ "myTest/demo_home/swagger_demo/gin/docs"
)

var swagHandler gin.HandlerFunc

// @title           Swagger Example API
// @version         1.0
// @description     This is a sample server.

// @contact.name   lixd
// @contact.name   ziyi
// @contact.url    https://github.com/ziyifast/ziyifast-code_instruction/tree/main/swagger_demo

// @license.name  Apache 2.0
// @license.url   http://www.apache.org/licenses/LICENSE-2.0.html

// @host      localhost:8080
// @BasePath  /api/v1

// SwaggerUI: http://localhost:8080/swagger/index.html
func main() {
	e := gin.Default()
	v1 := e.Group("/api/v1")
	{
		v1.GET("/hello", controller.Hello)
		v1.POST("/login", controller.Login)
	}
	e.GET("swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
	if swagHandler != nil {
		e.GET("/swagger/*any", swagHandler)
	}

	if err := e.Run(":8080"); err != nil {
		panic(err)
	}
}
controller/user_controller.go
package controller

import (
	ret "myTest/demo_home/swagger_demo/gin/response"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

// Hello 测试
// @Summary      测试SayHello
// @Description  向你说Hello
// @Tags         测试
// @Accept       json
// @Produce      json
// @Param        who  query     string  true             "人名"
// @Success      200  {string}  string  "{"msg": "hello  lixd"}"
// @Failure      400  {string}  string  "{"msg": "who    are  you"}"
// @Router       /hello [get]
func Hello(c *gin.Context) {
	who := c.Query("who")
	if who == "" {
		c.JSON(http.StatusBadRequest, gin.H{"msg": "who are u?"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"msg": "hello " + who})
}

type LoginReq struct {
	Username string `json:"username"`
	Password string `json:"password"`
}
type LoginResp struct {
	Token string `json:"token"`
}

// Login 登陆
// @Summary      登陆
// @Tags         登陆注册
// @Description  登入
// @Accept       json
// @Produce      json
// @Param        user  body      LoginReq                    true  "用户名密码"
// @Success      200   {object}  ret.Result{data=LoginResp}  "token"
// @Failure      400   {object}  ret.Result                  "错误提示"
// @Router       /login [post]
func Login(c *gin.Context) {
	var m LoginReq
	if err := c.ShouldBind(&m); err != nil {
		c.JSON(http.StatusBadRequest, ret.Fail("参数错误"))
		return
	}

	if m.Username == "admin" && m.Password == "123456" {
		resp := LoginResp{Token: strconv.Itoa(int(time.Now().Unix()))}
		c.JSON(http.StatusOK, ret.Success(resp))
		return
	}
	c.JSON(http.StatusUnauthorized, ret.Fail("user  or  password  error"))
}
response/response.go
// Package ret 统一返回结构
package ret

import (
	"net/http"
)

const (
	MsgSuccess = "success"
	MsgFail    = "fail"
)

type Result struct {
	Code int         `json:"code"`
	Data interface{} `json:"data"`
	Msg  string      `json:"msg"`
}

func Success(data interface{}, msg ...string) *Result {
	var m = MsgSuccess
	if len(msg) > 0 {
		m = msg[0]
	}
	return &Result{
		Code: http.StatusOK,
		Data: data,
		Msg:  m,
	}
}

func Fail(msg ...string) *Result {
	var m = MsgFail
	if len(msg) > 0 {
		m = msg[0]
	}
	return &Result{
		Code: http.StatusBadRequest,
		Data: "",
		Msg:  m,
	}
}

3 注解

3.1 swagger主文件注解-通用API信息

注释说明示例
title必填 应用程序的名称// @title Swagger Example API
version必填 提供应用程序API的版本。// @version 1.0
description应用程序的简短描述。// @description This is a sample server celler server.
tag.name标签的名称。// @tag.name This is the name of the tag
tag.description标签的描述。// @tag.description Cool Description
tag.docs.url标签的外部文档的URL。// @tag.docs.url https://example.com
tag.docs.description标签的外部文档说明。// @tag.docs.description Best example documentation
termsOfServiceAPI的服务条款。// @termsOfService http://swagger.io/terms/
contact.name公开的API的联系信息。// @contact.name API Support
contact.url联系信息的URL。 必须采用网址格式。// @contact.url
contact.email联系人/组织的电子邮件地址。 必须采用电子邮件地址的格式。// @contact.email support@swagger.io
license.name必填 用于API的许可证名称。// @license.name Apache 2.0
license.url用于API的许可证的URL。 必须采用网址格式。// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
host运行API的主机(主机名或IP地址)。// @host localhost:8080
BasePath运行API的基本路径。// @BasePath /api/v1
acceptAPI 可以使用的 MIME 类型列表。 请注意,Accept 仅影响具有请求正文的操作,例如 POST、PUT 和 PATCH。 值必须如“Mime类型”中所述。// @accept json
produceAPI可以生成的MIME类型的列表。值必须如“Mime类型”中所述。// @produce json
query.collection.format请求URI query里数组参数的默认格式:csv,multi,pipes,tsv,ssv。 如果未设置,则默认为csv。// @query.collection.format multi
schemes用空格分隔的请求的传输协议。// @schemes http https
x-name扩展的键必须以x-开头,并且只能使用json值// @x-example-key {“key”: “value”}

通用api信息,部分可以是在docs包里生成的,可以在项目启动的时候,或者在注册swagger路由的时候,修改掉部分信息,或者动态注入部分不固定的值,比如项目的基础路径:BasePath

func NewRouter() *gin.Engine {
	gin.SetMode("debug")
	engine := gin.New()
	docs.SwaggerInfo.BasePath = "/api/v2"
	engine.POST("/", v1.GetWord)
	engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
	engine.GET("/log/:id", client.ReadLokiLog)
	return engine
}

3.2 单个API样例

注释样例
description操作行为的详细说明。
description.markdown应用程序的简短描述。该描述将从名为endpointname.md的文件中读取。
id用于标识操作的唯一字符串。在所有API操作中必须唯一。
tags每个API操作的标签列表,以逗号分隔。
summary该操作的简短摘要。
acceptAPI 可以使用的 MIME 类型列表。 请注意,Accept 仅影响具有请求正文的操作,例如 POST、PUT 和 PATCH。 值必须如“Mime类型”中所述。
produceAPI可以生成的MIME类型的列表。值必须如“Mime类型”中所述。
param用空格分隔的参数。param name,param type,data type,is mandatory?,comment attribute(optional)
security每个API操作的安全性。
success以空格分隔的成功响应。return code,{param type},data type,comment
failure以空格分隔的故障响应。return code,{param type},data type,comment
response与success、failure作用相同
header以空格分隔的头字段。 return code,{param type},data type,comment
router以空格分隔的路径定义。 path,[httpMethod]
x-name扩展字段必须以x-开头,并且只能使用json值。

// @Summary 测试swagger
// @Tags test
// @version 1.0
// @Success 200 object FinalResult{data=v1.Application} 成功后返回值
// @Failure 500 object FinalResult 添加失败
// @Router / [get]
func GetWord(ctx *gin.Context) {
	application := &Application{Id: 1}
	err := ctx.BindJSON(application)
	if err != nil {
		ctx.JSON(500, "")
	}

	ctx.JSON(200, SuccessResult(application))
}

summary 是这个api的名字,可以显示在yapi的名称
tag 是这个api所在的分组
success 支持组合嵌套
param 说明了api需要的请求参数
param的类型支持:

  • query
  • path
  • header
  • body
  • formData

如果我们需要给字段添加注释,直接在字段后面添加即可

直接在参数属性后面增加注释,也可以指定参数的名称说明描述

type Application struct {
	Id   int    `json:"id" example:"2"`     // 环境ID
	Name string `json:"name" example:"环境一"` // Name 环境名称
}

忽略某个字段:

type Account struct {
    ID   string    `json:"id"`
    Name string     `json:"name"`
    Ignored int     `swaggerignore:"true"`
}

注意:如果代码中的swagger注释有修改,需要重新执行swag init生成文档

参考:https://blog.csdn.net/qq_38371367/article/details/123005909

bug

1 unknown field LeftDelim in struct literal of type "github.com/swaggo/swag

注意:如果遇到报错:
docs/docs.go:30:2: unknown field LeftDelim in struct literal of type “github.com/swaggo/swag”.Spec
可能是由于swag版本过低导致,升级版本即可:go get -u -v github.com/swaggo/swag/cmd/swag

2 添加了swag 注解,访问页面成功,但没有对应的方法

重新执行swag init,然后重新启动项目

  • 如果代码中的swagger注解有修改,需要重新执行swag init生成文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/375041.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何利用边缘计算网关进行机床数据采集,以提高数据采集的效率和准确性-天拓四方

边缘计算网关集成了数据采集、处理和传输功能的嵌入式设备。它位于传感器和执行器组成的设备层与云计算平台之间,能够实时处理和响应本地设备的数据请求,减轻云平台的压力,提高数据处理的速度和效率。同时,边缘计算网关还可以将处…

0206作业

TCP(传输控制协议)和 UDP(用户数据报协议)是两种常用的网络传输协议。它们之间的主要区别在于: 可靠性:TCP 是一种可靠的传输协议,它提供了数据传输的确认、重传和排序功能。如果数据在传输过程…

ROS笔记二:launch

目录 launch node标签 参数 参数服务器 节点分组 launch launch文件是一种可以可实现多节点启动和参数配置的xml文件,launch文件用于启动和配置ROS节点、参数和其他相关组件。launch文件通常使用XML格式编写,其主要目的是方便地启动ROS节点和设置节点之间的连…

一周学会Django5 Python Web开发-Django5介绍及安装

锋哥原创的Python Web开发 Django5视频教程: 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计10条视频,包括:2024版 Django5 Python we…

有奖讨论丨你能看出来哪些是 AI 写的代码么?

随着 AI 智能浪潮到来,AI 智能编码助手成为越来越多开发者的必备工具,Github Copilot、Amazon CodeWhisperer 等 AI 编码工具陆续登场,去年云栖大会阿里云发布的 “通义灵码” 同样令人期待。 通义灵码: https://tongyi.aliyun.co…

数据加密算法多样化的安全需求

数据加密算法是信息安全领域中非常重要的一环,它能够确保数据在传输和存储过程中的机密性和完整性。随着技术的发展,数据加密算法也在不断地演进和改进,以满足更为复杂和多样化的安全需求。 数据加密算法的基本原理是使用加密密钥和加密算法对…

86.分布式锁理论分析

文章目录 前言一、为什么需要分布式锁?二、基于 Redis 分布式锁怎么实现?三、Redis 分布锁存在的问题3.1 死锁问题3.2 锁过期时间问题3.3 锁被别人释放问题 四、Redis 分布锁小结五、Redis 主从同步对分布式锁的影响六、Redlock 方案七、Redlock 的争论7…

Java笔记 --- 七、多线程

七、多线程 线程 线程是操作系统能够运行调度的最小单位 被包含在进程之中,是进程的实际运行单位 应用软件中相互独立,可以同时运行的功能 每一个线程都有自己的栈 并发和并行 并发:在同一时刻,有多个指令在单个CPU上交替执…

Backtrader 文档学习- Observers - Benchmarking

Backtrader 文档学习- Observers - Benchmarking 1.概述 backtrader包括两种不同类型的对象,可以帮助跟踪: Observers 观察者Analyzers 分析器 在分析器领域中,已有TimeReturn对象,用于跟踪整个组合价值(即包括现金…

vue父子组件通讯的几种方式总结学习

一直都是公司前端在写组件,我想着自己也写一波,然后先看看父子组件传值的内容,想写一写小demo然后练习一下这个内容,也算是系统学习一下怎么处理这个内容 其实就是2种父传子和子传父 1.父组件传子组件数据 其实就是父在标签中可…

计算机网络-流量控制(数据链路层的流量控制及与传输层流量控制的区别 流量控制的方法 可靠传输,滑动窗口,流量控制三者关系)

文章目录 数据链路层的流量控制及与传输层流量控制的区别流量控制的方法各方法对应的发生窗口和接收窗口大小 可靠传输,滑动窗口,流量控制三者关系小结 数据链路层的流量控制及与传输层流量控制的区别 端到端:两个主机之间的 点对点&#xf…

恒创科技:服务器内存不足影响大吗?

​  服务器在为网站、应用程序和在线服务提供支持方面发挥着关键作用。这些服务器需要提供最佳性能,以确保正常无缝的用户体验,而RAM是显著影响服务器性能的关键配置之一。 RAM 是一种随机存取存储器,计算机和服务器使用它来临时存储正在使…

VM安装Centos7

目标: 一,安装Centos7 二,ssh可以连接 1 新建虚拟机 一直下一步 2 直到此处,选择稍后安装 一直下一步直到完成。 3 选中虚拟机,点击设置 选择CD/DVD,选取ISO映像文件。 4 等待安装 并且设置root密码 5…

苹果证书过期有什么影响

引言 苹果证书是一种数字签名,用于验证应用程序的身份和完整性。然而,若该证书过期,将会对用户和开发者带来一定的影响。在本文中,我们将详细介绍苹果证书过期的原理和影响,并提供一些解决方法。 苹果证书的原理 苹…

机器学习 | 探索朴素贝叶斯算法的应用

朴素贝叶斯算法是一种基于贝叶斯定理和特征条件独立假设的分类算法。它被广泛应用于文本分类、垃圾邮件过滤、情感分析等领域,并且在实际应用中表现出色。 朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法: 1)对于给定的待分类项r…

Redis(十三)缓存双写一致性策略

文章目录 概述示例 缓存双写一致性缓存按照操作来分,细分2种读写缓存:同步直写策略读写缓存:异步缓写策略双检加锁策略 数据库和缓存一致性更新策略先更新数据库,再更新缓存先更新缓存,再更新数据库先删除缓存&#xf…

【el-tree 文字过长处理方案】

文字过长处理方案 一、示例代码二、关键代码三、效果图 一、示例代码 <divstyle"height: 600px;overflow: auto"class"text item"><el-treeref"tree":data"treeData":props"defaultProps"class"filter-tree&…

C++ 语法文件

程序运行时产生的数据都属于临时数据&#xff0c;程序结束就会被释放。 通过文件可以可以将数据持久化 c中对文件操作需要包含头文件fstream 文件的类型分为两种 1.文本文件 文件以文本的ASCII码形式存储在计算机中 2.二进制文件 稳重以文本的二进制形式存储在计算机中 用…

【云原生之kubernetes系列】--HPA自动伸缩

HPA自动伸缩 HorizontalPodAutoscaler&#xff08;简称 HPA &#xff09;自动更新工作负载资源&#xff08;例如Deployment或者Statefulset)&#xff0c;目的是让pod可以自动扩缩工作负载以满足业务需求。 水平扩缩意味着对增加的负载的响应是部署更多的Pod。这与“垂直&…

MIT_线性代数笔记:第 34 讲 总复习

目录 试题1试题2试题3试题4试题5 本讲为线性代数课程总复习&#xff0c;复习的方法就是做往年试题。 试题1 1&#xff09;已知 Ax [ 1 0 0 ] \begin{bmatrix} 1\\0\\0 \end{bmatrix} ​100​ ​ 无解&#xff0c;Ax [ 0 1 0 ] \begin{bmatrix} 0\\1\\0 \end{bmatrix} ​010​ …