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

在CSDN学Golang场景化解决方案(基于gin框架的web开发脚手架)

一,中间件统一实现Oauth2身份验证

在Golang基于Gin框架开发Web应用程序时,可以使用gin-oauth2来实现Oauth2身份验证。下面是简单的步骤:

  1. 安装gin-oauth2包:go get github.com/appleboy/gin-oauth2
  2. 导入依赖:import "github.com/appleboy/gin-oauth2"
  3. 创建oauth2中间件:
func oauthMiddleware() gin.HandlerFunc {return func(c *gin.Context) {config := oauth2.Config{ClientID:     "CLIENT_ID",ClientSecret: "CLIENT_SECRET",Endpoint:     google.Endpoint,}token, err := oauth2.New(config).ValidateToken(c.Request)if err != nil {c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid Token"})c.Abort()return}// 将token存储到context中以供后续处理使用c.Set("token", token)}
}
  1. 在路由中使用oauth2中间件:
router.GET("/private", oauthMiddleware(), func(c *gin.Context) {// 从context中获取token并进行相关处理token, exists := c.Get("token")if !exists {// handle error}...
})

这样,在访问路由"/private"之前,会先执行oauthMiddleware()函数进行身份验证,只有通过验证才能访问该路由。

需要注意的是,以上示例使用了Google作为OAuth提供商,如果你要使用其他提供商,请根据其文档更新配置信息即可。

二,路由分组api版本控制

在Golang基于Gin框架开发Web应用程序时,可以使用路由分组和api版本控制来管理不同版本的API。下面是简单的步骤:

  1. 导入依赖:import "github.com/gin-gonic/gin"
  2. 创建路由组:
v1 := router.Group("/v1")
{v1.GET("/users", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "API V1"})})
}
v2 := router.Group("/v2")
{v2.GET("/users", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "API V2"})})
}
  1. 在需要进行版本控制的地方,根据请求头部信息决定调用哪个版本的API:
router.GET("/users", func(c *gin.Context) {version := c.GetHeader("Accept-Version")switch version {case "application/vnd.example.v1+json":// 调用V1版本的APIbreakcase "application/vnd.example.v2+json":// 调用V2版本的APIbreakdefault:// 版本不支持或未指定c.JSON(http.StatusUnsupportedMediaType, gin.H{"error": "Unsupported Media Type"})return}
})

这样,在访问"/v1/users"或"/v2/users"时,会分别调用对应版本的API;而在访问"/users"时,则会根据请求头部信息来决定调用哪个版本的API。

需要注意的是,以上示例中使用了自定义的请求头部信息来指定API版本,如果你想使用其他方式进行版本控制,也可以根据实际情况进行修改。

三,jwt实现客户端令牌

在Golang基于Gin框架开发Web应用程序时,可以使用JWT(JSON Web Token)来实现客户端令牌。下面是简单的步骤:

  1. 导入依赖:import "github.com/dgrijalva/jwt-go"
  2. 定义JWT生成函数:
func generateToken(userId int64) (string, error) {token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{"userId": userId,"exp": time.Now().Add(time.Hour * 24).Unix(),})return token.SignedString([]byte("your-secret-key"))
}
  1. 定义JWT验证中间件:
func authMiddleware() gin.HandlerFunc {return func(c *gin.Context) {tokenString := c.GetHeader("Authorization")if tokenString == "" {c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})return}claims := jwt.MapClaims{}token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {return []byte("your-secret-key"), nil})if err != nil || !token.Valid {c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid Token"})return}userIdFloat64, ok := claims["userId"].(float64)if !ok {c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid User ID"})return}userId := int64(userIdFloat64)// 将用户ID存储到上下文中,以便后续使用c.Set("userId", userId)// 继续处理请求c.Next()}
}
  1. 在需要进行认证的路由上应用中间件:
router.GET("/users/:id", authMiddleware(), func(c *gin.Context) {userId := c.GetInt64("userId")id, err := strconv.ParseInt(c.Param("id"), 10, 64)if err != nil || userId != id {c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})return}// 处理请求...
})

这样,在访问"/users/:id"时,会检查请求头部信息中的Authorization字段是否为有效的JWT令牌,并将其中包含的用户ID存储到上下文中。在后续处理中,可以通过从上下文中获取用户ID来实现权限控制。

需要注意的是,以上示例中使用了简单的对称加密方式来生成和验证JWT令牌,如果你想使用其他加密算法或更复杂的认证方案,也可以根据实际情况进行修改。

四,logurs日志组件封装

在Golang基于Gin框架开发Web应用程序时,可以使用logrus来实现日志记录。下面是一个简单的封装示例:

  1. 导入依赖:import log "github.com/sirupsen/logrus"
  2. 定义初始化函数:
func initLogger() {// 设置日志格式为JSON格式log.SetFormatter(&log.JSONFormatter{})// 设置日志级别为debug以上log.SetLevel(log.DebugLevel)// 输出到文件file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)if err == nil {log.SetOutput(file)} else {log.Info("Failed to log to file, using default stderr")}// 输出到控制台log.SetOutput(os.Stdout)
}
  1. 在main函数中调用初始化函数:
func main() {initLogger()// ...router.Run(":8080")
}
  1. 封装logger对象:
type Logger struct {
}func (l *Logger) Info(args ...interface{}) {log.Info(args...)
}func (l *Logger) Warn(args ...interface{}) {log.Warn(args...)
}func (l *Logger) Error(args ...interface{}) {log.Error(args...)
}func (l *Logger) Fatal(args ...interface{}) {log.Fatal(args...)
}func (l *Logger) Panic(args ...interface{}) {log.Panic(args...)
}
  1. 在需要记录日志的地方使用封装后的logger对象:
logger := &Logger{}
logger.Info("message")

这样,在记录日志时,就可以通过封装后的logger对象来实现。

需要注意的是,以上示例中使用了logrus来输出日志到文件和控制台。如果你想使用其他方式(例如输出到ELK等),也可以根据实际情况进行修改。

五,分布式日志链路追踪设计

在Golang基于Gin框架开发Web应用程序时,为了方便进行分布式日志链路追踪,可以使用Jaeger等开源工具。下面是一个简单的设计示例:

  1. 导入依赖:import ( "github.com/gin-gonic/gin" opentracing "github.com/opentracing/opentracing-go" jaegercfg "github.com/uber/jaeger-client-go/config" log "github.com/sirupsen/logrus" )
  2. 定义初始化函数:
func initTracer() {// 配置jaeger客户端cfg, err := jaegercfg.FromEnv()if err != nil {log.WithError(err).Fatal("Could not parse Jaeger env vars")}tracer, closer, err := cfg.NewTracer(jaegercfg.Logger(log.StandardLogger()))if err != nil {log.WithError(err).Fatal("Could not initialize jaeger tracer")}// 设置全局traceropentracing.SetGlobalTracer(tracer)// 注册gin中间件router.Use(func(c *gin.Context) {spanCtx, _ := tracer.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(c.Request.Header))span := tracer.StartSpan(c.Request.URL.Path, ext.RPCServerOption(spanCtx))defer span.Finish()c.Set("span", span)c.Next()statusCode := c.Writer.Status()if statusCode >= 400 && statusCode < 500 {span.SetTag("error", true)} else {span.SetTag("success", true)}span.SetTag("http.status_code", statusCode)})// defer关闭tracerdefer closer.Close()
}
  1. 在main函数中调用初始化函数:
func main() {initTracer()// ...router.Run(":8080")
}
  1. 在需要进行日志记录的地方,使用上下文中的span对象进行追踪:
func someHandler(c *gin.Context) {span, ok := c.Get("span")if !ok {log.Error("Could not retrieve span from context")return}// 使用span记录日志和追踪span.LogFields(log.Fields{"event": "some_event","value": 42,})// ...
}

这样,在Web应用程序中就可以通过Jaeger等开源工具,实现方便的分布式日志链路追踪了。

Golang云原生学习路线图、教学视频、文档资料、面试题资料(资料包括C/C++、K8s、golang项目实战、gRPC、Docker、DevOps等)免费分享 有需要的可以加qun:793221798领取

六,EFK统一日志采集

在Golang基于Gin框架开发Web应用程序时,可以使用EFK等工具实现统一日志采集。下面是一个简单的设计示例:

  1. 导入依赖:import ( "github.com/gin-gonic/gin" "github.com/elastic/go-elasticsearch/v7" "go.uber.org/zap" )
  2. 初始化Logger:
func initLogger() {config := zap.NewDevelopmentConfig()logger, err := config.Build()if err != nil {log.WithError(err).Fatal("Could not initialize logger")}// 设置全局Loggerzap.ReplaceGlobals(logger)
}
  1. 在main函数中调用初始化函数:
func main() {initLogger()// ...router.Run(":8080")
}
  1. 定义logrus-zap-hook并注册到logrus中:
type LogrusZapHook struct {}func (hook *LogrusZapHook) Levels() []log.Level {return log.AllLevels
}func (hook *LogrusZapHook) Fire(entry *log.Entry) error {switch entry.Level {case log.DebugLevel:zap.L().Debug(entry.Message)case log.InfoLevel:zap.L().Info(entry.Message)case log.WarnLevel:zap.L().Warn(entry.Message)case log.ErrorLevel:zap.L().Error(entry.Message)case log.FatalLevel:zap.L().Fatal(entry.Message)default:panic(fmt.Sprintf("Unhandled log level: %v", entry.Level))}return nil
}func registerLogrusZapHook() {hook := &LogrusZapHook{}log.AddHook(hook)
}
  1. 在需要进行日志记录的地方,使用logrus进行记录:
func someHandler(c *gin.Context) {// 使用logrus记录日志log.WithFields(log.Fields{"event": "some_event","value": 42,}).Info("Hello, world!")// ...
}
  1. 配置EFK中的Logstash或Filebeat等采集工具,将应用程序的日志发送到Elasticsearch。

这样,在Web应用程序中就可以通过EFK等工具,实现统一的日志采集和管理了。

七,viper配置文件读取

在Golang基于Gin框架开发Web应用程序时,可以使用Viper库实现配置文件读取。下面是一个简单的设计示例:

  1. 导入依赖:import ( "github.com/gin-gonic/gin" "github.com/spf13/viper" )
  2. 初始化Viper:
func initViper() {viper.SetConfigName("config") // 配置文件名字viper.AddConfigPath(".") // 配置文件所在路径err := viper.ReadInConfig()if err != nil {log.WithError(err).Fatal("Could not read config file")}
}
  1. 在main函数中调用初始化函数:
func main() {initViper()// ...router.Run(":8080")
}
  1. 定义配置结构体,并使用viper将配置信息绑定到结构体上:
type Config struct {Mode     string `mapstructure:"mode"`Port     int    `mapstructure:"port"`
}func readConfig() (*Config, error) {config := &Config{}err := viper.Unmarshal(config)if err != nil {return nil, err}return config, nil
}
  1. 在需要访问配置信息的地方,通过读取配置结构体来获取配置信息:
func someHandler(c *gin.Context) {config := &Config{}err := viper.Unmarshal(config)if err != nil {log.WithError(err).Error("Failed to read configuration")return}mode := config.Modeport := config.Port// ...
}

这样,在Web应用程序中就可以使用Viper库,方便地读取配置文件中的信息了。

八,etcd应用配置中心

在Golang基于Gin框架开发Web应用程序时,可以使用Etcd作为应用配置中心。下面是一个简单的设计示例:

  1. 导入依赖:import ( "github.com/gin-gonic/gin" "go.etcd.io/etcd/clientv3" )
  2. 初始化Etcd客户端:
func initEtcd() (*clientv3.Client, error) {config := clientv3.Config{Endpoints: []string{"http://localhost:2379"},}client, err := clientv3.New(config)if err != nil {return nil, err}return client, nil
}
  1. 在main函数中调用初始化函数:
func main() {etcdClient, err := initEtcd()if err != nil {log.WithError(err).Fatal("Could not connect to Etcd")}// ...router.Run(":8080")
}
  1. 定义获取配置信息的函数,并通过Etcd客户端从配置中心读取配置信息:
type Config struct {Mode     string `json:"mode"`Port     int    `json:"port"`
}func getConfig(client *clientv3.Client) (*Config, error) {resp, err := client.Get(context.Background(), "/app/config")if err != nil {return nil, err}for _, kv := range resp.Kvs {var config Configerr = json.Unmarshal(kv.Value, &config)if err != nil {return nil, err}return &config, nil}return nil, errors.New("no configuration found in Etcd")
}
  1. 在需要访问配置信息的地方,通过调用获取配置函数来获取配置信息:
func someHandler(c *gin.Context) {config, err := getConfig(etcdClient)if err != nil {log.WithError(err).Error("Failed to read configuration")return}mode := config.Modeport := config.Port// ...
}

这样,在Web应用程序中就可以使用Etcd作为应用配置中心,实现动态配置管理了。

九,redis数据缓存

在Golang基于Gin框架开发Web应用程序时,可以使用Redis作为数据缓存。下面是一个简单的设计示例:

  1. 导入依赖:import ( "github.com/gin-gonic/gin" "github.com/go-redis/redis/v8" )
  2. 初始化Redis客户端:
func initRedis() *redis.Client {return redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "", // no password setDB:       0,  // use default DB})
}
  1. 在main函数中调用初始化函数:
func main() {redisClient := initRedis()// ...router.Run(":8080")
}
  1. 定义获取数据的函数,并通过Redis客户端从缓存中读取数据:
func getDataFromCache(redisClient *redis.Client, key string) (string, error) {data, err := redisClient.Get(context.Background(), key).Result()if err != nil && err != redis.Nil {return "", err}return data, nil
}
  1. 定义写入数据的函数,并通过Redis客户端将数据写入缓存:
func setDataToCache(redisClient *redis.Client, key string, value interface{}, expiration time.Duration) error {err := redisClient.Set(context.Background(), key, value, expiration).Err()if err != nil {return err}return nil
}
  1. 在需要访问数据的地方,通过调用获取或写入数据的函数来进行操作:
func someHandler(c *gin.Context) {data, err := getDataFromCache(redisClient, "data_key")if err != nil {log.WithError(err).Error("Failed to read data from cache")return}if data == "" {// 数据不存在缓存中,需要从其他数据源获取,并将其写入缓存// ...err = setDataToCache(redisClient, "data_key", someData, 10*time.Minute)if err != nil {log.WithError(err).Error("Failed to write data to cache")return}data = someData}// 处理数据// ...
}

这样,在Web应用程序中就可以使用Redis作为数据缓存了。在处理请求时,首先尝试从Redis缓存中获取数据,如果数据不存在,则从其他数据源获取,并将其写入Redis缓存。下次再有相同的请求时,直接从Redis缓存中读取即可。

十,mysql数据存储

在Golang基于Gin框架开发Web应用程序时,可以使用MySQL作为数据存储。下面是一个简单的设计示例:

  1. 导入依赖:import ( "github.com/gin-gonic/gin" "gorm.io/gorm" "gorm.io/driver/mysql" )
  2. 初始化数据库:
func initDB() (*gorm.DB, error) {dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {return nil, err}return db, nil
}
  1. 在main函数中调用初始化函数,并迁移模型:
func main() {db, err := initDB()if err != nil {log.Fatal(err)}// 迁移模型err = db.AutoMigrate(&User{})if err != nil {log.Fatal(err)}// ...router.Run(":8080")
}
  1. 定义模型结构体:
type User struct {gorm.ModelName  string `json:"name"`Email string `json:"email"`
}
  1. 定义处理请求的函数,通过ORM操作数据库:
func createUser(c *gin.Context) {var user Usererr := c.ShouldBindJSON(&user)if err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})return}result := db.Create(&user)if result.Error != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})return}c.JSON(http.StatusCreated, user)
}
  1. 在需要访问数据的地方,通过调用ORM方法来进行操作:
func getUser(c *gin.Context) {var user Userid := c.Param("id")result := db.First(&user, id)if result.Error != nil {if errors.Is(result.Error, gorm.ErrRecordNotFound) {c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})} else {c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user"})}return}c.JSON(http.StatusOK, user)
}

这样,在Web应用程序中就可以使用MySQL作为数据存储了。在处理请求时,通过ORM操作数据库进行增删改查等操作。

相关文章:

在CSDN学Golang场景化解决方案(基于gin框架的web开发脚手架)

一&#xff0c;中间件统一实现Oauth2身份验证 在Golang基于Gin框架开发Web应用程序时&#xff0c;可以使用gin-oauth2来实现Oauth2身份验证。下面是简单的步骤&#xff1a; 安装gin-oauth2包&#xff1a;go get github.com/appleboy/gin-oauth2导入依赖&#xff1a;import &q…...

关于Express 5

目录 1、概述 2、Express 5的变化 2.1 弃用或删除内容的列表&#xff1a; app.param&#xff08;name&#xff0c;fn&#xff09;名称中的前导冒号&#xff08;&#xff1a;&#xff09; app.del() app.param&#xff08;fn&#xff09; 复数方法名 res.json&#xff0…...

ftrace 原理详细分析

》内核新视界文章汇总《 文章目录 ftrace 原理分析1 简介2 ftrace 的编译器支持2.1 HAVE_FUNCTION_TRACER 选项对 ftrace 的支持2.2 HAVE_DYNAMIC_FTRACE 选项对动态 ftrace 的支持 3 ftrace 的初始化4 function trace 流程5 总结 ftrace 原理分析 1 简介 ftrace 是一个内核…...

UWB定位技术和蓝牙AOA有哪些不同?-高精度室内定位技术对比

UWB超宽带定位 UWB&#xff08;Ultra Wide Band &#xff09;即超宽带技术&#xff0c;它是一种无载波通信技术&#xff0c;利用纳秒级的非正弦波窄脉冲传输数据&#xff0c;因此其所占的频谱范围很宽。传统的定位技术是根据信号强弱来判别物体位置&#xff0c;信号强弱受外界…...

【RabbitMQ】golang客户端教程2——工作队列

任务队列/工作队列 在上一个教程中&#xff0c;我们编写程序从命名的队列发送和接收消息。在这一节中&#xff0c;我们将创建一个工作队列&#xff0c;该队列将用于在多个工人之间分配耗时的任务。 工作队列&#xff08;又称任务队列&#xff09;的主要思想是避免立即执行某些…...

芯旺微冲刺IPO,车规级MCU竞争白热化下的“隐忧”凸显

在汽车智能化和电动化发展带来的巨大蓝海市场下&#xff0c;产业链企业迎来了一波IPO小高潮。 日前&#xff0c;上海芯旺微电子技术股份有限公司&#xff08;以下简称“芯旺微”&#xff09;在科创板的上市申请已经被上交所受理&#xff0c;拟募资17亿元&#xff0c;用于投建车…...

HTML <s> 标签

例子 可以像这样标记删除线文本&#xff1a; 在 HTML 5 中&#xff0c;<s>仍然支持</s>已经不支持这个标签了。 浏览器支持 元素ChromeIEFirefoxSafariOpera<s>YesYesYesYesYes 所有浏览器都支持 <s> 标签。 定义和用法 <s> 标签可定义加…...

微信小程序 - scroll-view组件之上拉加载下拉刷新(解决上拉加载不触发)

前言 最近在做微信小程序项目中&#xff0c;有一个功能就是做一个商品列表分页限流然后实现上拉加载下拉刷新功能&#xff0c;遇到了一个使用scroll-viwe组件下拉刷新事件始终不触发问题&#xff0c;网上很多说给scroll-view设置一个高度啥的就可以解决&#xff0c;有些人设置了…...

rust usize与i64怎么比较大小?

在Rust中&#xff0c; usize 和 i64 是不同的整数类型&#xff0c;它们的位数和表示范围可能不同。因此&#xff0c;直接比较 usize 和 i64 是不允许的。如果需要比较它们的大小&#xff0c;可以将它们转换为相同的类型&#xff0c;然后进行比较。 要将 usize 转换为 i64 &…...

电脑更新win10黑屏解决方法

电脑更新win10黑屏解决方法 电脑黑屏出现原因解决步骤 彻底解决 电脑黑屏 出现原因 系统未更新成功就关机&#xff0c;导致系统出故障无法关机 解决步骤 首先长安电源键10s关机 按电源键开机&#xff0c;出现logo时按F8进入安全模式。 进入自动修复环境后&#xff0c;单击…...

STM32入门——外部中断

中断系统概述 中断&#xff1a;在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&#xff0c;处理完成后又返回原来被暂停的位置继续运行中断优先级&#xff…...

【计算机网络】NAT及Bridge介绍

OSI七层模型 七层模型介绍及举例 为通过网络将人类可读信息通过网络从一台设备传输到另一台设备&#xff0c;必须在发送设备沿 OSI 模型的七层结构向下传输数据&#xff0c;然后在接收端沿七层结构向上传输数据。 数据在 OSI 模型中如何流动 库珀先生想给帕尔梅女士发一封电…...

封装动态SQL的插件

最近根据公司的业务需要封装了一个简单的动态SQL的插件&#xff0c;要求是允许用户在页面添加SQL的where条件&#xff0c;然后开发者只需要给某个接口写查询对应的表&#xff0c;参数全部由插件进行拼接完成。下面是最终实现&#xff1a; 开发人员只需要在接口写上下面的查询SQ…...

C# Microsoft消息队列服务器的使用 MSMQ

先安装消息队列服务器 private static readonly string path ".\\Private$\\myQueue";private void Create(){if (!MessageQueue.Exists(path)){MessageQueue.Create(path);}}private void Send(){Stopwatch stopwatch new Stopwatch();stopwatch.Start();Message…...

Kafka3.0.0版本——生产者如何提高吞吐量

目录 一、生产者提高吞吐量参数设置二、产者提高吞吐量代码示例 一、生产者提高吞吐量参数设置 batch.size&#xff1a;设置批次大小&#xff0c;默认16klinger.ms&#xff1a;设置等待时间&#xff0c;修改为5-100msbuffer.memory&#xff1a;设置缓冲区大小&#xff0c; 默认…...

js精度丢失的问题

1.js精度丢失的常见问题,从常见的浮点型进行计算&#xff0c;到位数很长的munber类型进行计算都会造成精度丢失的问题&#xff0c; 首先我们看一个问题&#xff1a; 0.1 0.2 ! 0.3 // truelet a 9007199254740992 a 1 a // true那么js为什么会出现精度丢失的问题&…...

C++ 编译预处理

在编译器对源程序进行编译时&#xff0c;首先要由处理器对程序文本进行预处理。预处理器提供了一组编译预处理指令和预处理操作符。预处理指令实际上不是C语言的一部分&#xff0c;它只是用来扩充C程序设计环境。所有的预处理指令在程序中都以“#”来引导&#xff0c;每一条预处…...

备战秋招 | 笔试强化22

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、在有序双向链表中定位删除一个元素的平均时间复杂度为 A. O(1) B. O(N) C. O(logN) D. O(N*logN) 2、在一个以 h 为头指针的单循环链表中&#xff0c;p 指针指向链尾结点的条件是( ) A. p->ne…...

LeetCode ACM模式——哈希表篇(二)

刷题顺序及思路来源于代码随想录&#xff0c;网站地址&#xff1a;https://programmercarl.com 202. 快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复…...

hadoop 3.1.3集群搭建 ubuntu20

相关 hyper-v安装ubuntu-20-server hyper-v建立快照 hyper-v快速创建虚拟机-导入导出虚拟机 准备 虚拟机设置 采用hyper-v方式安装ubuntu-20虚拟机和koolshare hostnameiph01192.168.66.20h02192.168.66.21h03192.168.66.22 静态IP 所有机器都需要按需设置 sudo vim /e…...

备忘录模式——撤销功能的实现

1、简介 1.1、概述 备忘录模式提供了一种状态恢复的实现机制&#xff0c;使得用户可以方便地回到一个特定的历史步骤。当新的状态无效或者存在问题时&#xff0c;可以使用暂时存储起来的备忘录将状态复原。当前很多软件都提供了撤销&#xff08;Undo&#xff09;操作&#xf…...

Golang 函数参数的传递方式 值传递,引用传递

基本介绍 我们在讲解函数注意事项和使用细节时&#xff0c;已经讲过值类型和引用类型了&#xff0c;这里我们再系统总结一下&#xff0c;因为这是重难点&#xff0c;值类型参数默认就是值传递&#xff0c;而引用类型参数默认就是引用传递。 两种传递方式&#xff08;函数默认都…...

K8s影响Pod调度和Deployment

5.应用升级回滚和弹性伸缩...

透明代理和不透明代理

透明代理和不透明代理 1、透明代理(Transparent Proxy)2、不透明代理(Non-Transparent Proxy)3、工作原理4、透明代理为啥比不透明代理多一部先连接到路由再到代理服务器?5、这里路由器做了什么工作6、代理自动配置文件(Proxy Auto-Configuration file,PAC file)7、代理…...

1424. 对角线遍历 II;2369. 检查数组是否存在有效划分;1129. 颜色交替的最短路径

1424. 对角线遍历 II 核心思想&#xff1a;我感觉是一个技巧题&#xff0c;如果想到很容易做出了&#xff0c;想不到就很难了。首先对于一条对角线的数&#xff0c;其坐标ij是一样的&#xff0c;然后同一条对角线斜向上的j是从小到大的&#xff0c;知道这个就很容易做出来了。…...

【漏洞复现】Metabase 远程命令执行漏洞(CVE-2023-38646)

文章目录 前言声明一、漏洞介绍二、影响版本三、漏洞原理四、漏洞复现五、修复建议 前言 Metabase 0.46.6.1之前版本和Metabase Enterprise 1.46.6.1之前版本存在安全漏洞&#xff0c;未经身份认证的远程攻击者利用该漏洞可以在服务器上以运行 Metabase 服务器的权限执行任意命…...

Linux 9的repo for OVS build

源码中自带RPM包spec文件 cd /root/rpmbuild/SOURCES/openvswitch-2.17.7/rhel rpmbuild -bb openvswitch.spec ## 按提示解决&#xff0c;不好解决的依赖可以试试下面的repo 方法 error: File /root/rpmbuild/SOURCES/openvswitch-2.17.7.tar.gz: No such file or direct…...

DOCTYPE 是什么作用?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ DOCTYPE 是什么作用&#xff1f;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴…...

KubeSphere 3.4.0 发布:支持 K8s v1.26

2023 年 07 月 26 日&#xff0c;KubeSphere 开源社区激动地向大家宣布&#xff0c;KubeSphere 3.4.0 正式发布&#xff01; 让我们先简单回顾下之前三个大版本的主要变化&#xff1a; KubeSphere 3.1.0 新增了“边缘计算”、“计量计费” 等功能&#xff0c;将 Kubernetes 从…...

自然语言文本分类模型代码

以下是一个基于PyTorch的文本分类模型的示例代码&#xff0c;用于将给定的文本分为多个预定义类别&#xff1a; import torch import torch.nn as nn import torch.nn.functional as Fclass TextClassifier(nn.Module):def __init__(self, vocab_size, embedding_dim, hidden_…...