在CSDN学Golang场景化解决方案(基于gin框架的web开发脚手架)
一,中间件统一实现Oauth2身份验证
在Golang基于Gin框架开发Web应用程序时,可以使用gin-oauth2来实现Oauth2身份验证。下面是简单的步骤:
- 安装gin-oauth2包:
go get github.com/appleboy/gin-oauth2 - 导入依赖:
import "github.com/appleboy/gin-oauth2" - 创建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)}
}
- 在路由中使用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。下面是简单的步骤:
- 导入依赖:
import "github.com/gin-gonic/gin" - 创建路由组:
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"})})
}
- 在需要进行版本控制的地方,根据请求头部信息决定调用哪个版本的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)来实现客户端令牌。下面是简单的步骤:
- 导入依赖:
import "github.com/dgrijalva/jwt-go" - 定义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"))
}
- 定义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()}
}
- 在需要进行认证的路由上应用中间件:
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来实现日志记录。下面是一个简单的封装示例:
- 导入依赖:
import log "github.com/sirupsen/logrus" - 定义初始化函数:
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)
}
- 在main函数中调用初始化函数:
func main() {initLogger()// ...router.Run(":8080")
}
- 封装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...)
}
- 在需要记录日志的地方使用封装后的logger对象:
logger := &Logger{}
logger.Info("message")
这样,在记录日志时,就可以通过封装后的logger对象来实现。
需要注意的是,以上示例中使用了logrus来输出日志到文件和控制台。如果你想使用其他方式(例如输出到ELK等),也可以根据实际情况进行修改。
五,分布式日志链路追踪设计
在Golang基于Gin框架开发Web应用程序时,为了方便进行分布式日志链路追踪,可以使用Jaeger等开源工具。下面是一个简单的设计示例:
- 导入依赖:
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" ) - 定义初始化函数:
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()
}
- 在main函数中调用初始化函数:
func main() {initTracer()// ...router.Run(":8080")
}
- 在需要进行日志记录的地方,使用上下文中的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等工具实现统一日志采集。下面是一个简单的设计示例:
- 导入依赖:
import ( "github.com/gin-gonic/gin" "github.com/elastic/go-elasticsearch/v7" "go.uber.org/zap" ) - 初始化Logger:
func initLogger() {config := zap.NewDevelopmentConfig()logger, err := config.Build()if err != nil {log.WithError(err).Fatal("Could not initialize logger")}// 设置全局Loggerzap.ReplaceGlobals(logger)
}
- 在main函数中调用初始化函数:
func main() {initLogger()// ...router.Run(":8080")
}
- 定义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)
}
- 在需要进行日志记录的地方,使用logrus进行记录:
func someHandler(c *gin.Context) {// 使用logrus记录日志log.WithFields(log.Fields{"event": "some_event","value": 42,}).Info("Hello, world!")// ...
}
- 配置EFK中的Logstash或Filebeat等采集工具,将应用程序的日志发送到Elasticsearch。
这样,在Web应用程序中就可以通过EFK等工具,实现统一的日志采集和管理了。
七,viper配置文件读取
在Golang基于Gin框架开发Web应用程序时,可以使用Viper库实现配置文件读取。下面是一个简单的设计示例:
- 导入依赖:
import ( "github.com/gin-gonic/gin" "github.com/spf13/viper" ) - 初始化Viper:
func initViper() {viper.SetConfigName("config") // 配置文件名字viper.AddConfigPath(".") // 配置文件所在路径err := viper.ReadInConfig()if err != nil {log.WithError(err).Fatal("Could not read config file")}
}
- 在main函数中调用初始化函数:
func main() {initViper()// ...router.Run(":8080")
}
- 定义配置结构体,并使用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
}
- 在需要访问配置信息的地方,通过读取配置结构体来获取配置信息:
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作为应用配置中心。下面是一个简单的设计示例:
- 导入依赖:
import ( "github.com/gin-gonic/gin" "go.etcd.io/etcd/clientv3" ) - 初始化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
}
- 在main函数中调用初始化函数:
func main() {etcdClient, err := initEtcd()if err != nil {log.WithError(err).Fatal("Could not connect to Etcd")}// ...router.Run(":8080")
}
- 定义获取配置信息的函数,并通过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")
}
- 在需要访问配置信息的地方,通过调用获取配置函数来获取配置信息:
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作为数据缓存。下面是一个简单的设计示例:
- 导入依赖:
import ( "github.com/gin-gonic/gin" "github.com/go-redis/redis/v8" ) - 初始化Redis客户端:
func initRedis() *redis.Client {return redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "", // no password setDB: 0, // use default DB})
}
- 在main函数中调用初始化函数:
func main() {redisClient := initRedis()// ...router.Run(":8080")
}
- 定义获取数据的函数,并通过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
}
- 定义写入数据的函数,并通过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
}
- 在需要访问数据的地方,通过调用获取或写入数据的函数来进行操作:
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作为数据存储。下面是一个简单的设计示例:
- 导入依赖:
import ( "github.com/gin-gonic/gin" "gorm.io/gorm" "gorm.io/driver/mysql" ) - 初始化数据库:
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
}
- 在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")
}
- 定义模型结构体:
type User struct {gorm.ModelName string `json:"name"`Email string `json:"email"`
}
- 定义处理请求的函数,通过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)
}
- 在需要访问数据的地方,通过调用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开发脚手架)
一,中间件统一实现Oauth2身份验证 在Golang基于Gin框架开发Web应用程序时,可以使用gin-oauth2来实现Oauth2身份验证。下面是简单的步骤: 安装gin-oauth2包:go get github.com/appleboy/gin-oauth2导入依赖:import &q…...
关于Express 5
目录 1、概述 2、Express 5的变化 2.1 弃用或删除内容的列表: app.param(name,fn)名称中的前导冒号(:) app.del() app.param(fn) 复数方法名 res.json࿰…...
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(Ultra Wide Band )即超宽带技术,它是一种无载波通信技术,利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。传统的定位技术是根据信号强弱来判别物体位置,信号强弱受外界…...
【RabbitMQ】golang客户端教程2——工作队列
任务队列/工作队列 在上一个教程中,我们编写程序从命名的队列发送和接收消息。在这一节中,我们将创建一个工作队列,该队列将用于在多个工人之间分配耗时的任务。 工作队列(又称任务队列)的主要思想是避免立即执行某些…...
芯旺微冲刺IPO,车规级MCU竞争白热化下的“隐忧”凸显
在汽车智能化和电动化发展带来的巨大蓝海市场下,产业链企业迎来了一波IPO小高潮。 日前,上海芯旺微电子技术股份有限公司(以下简称“芯旺微”)在科创板的上市申请已经被上交所受理,拟募资17亿元,用于投建车…...
HTML <s> 标签
例子 可以像这样标记删除线文本: 在 HTML 5 中,<s>仍然支持</s>已经不支持这个标签了。 浏览器支持 元素ChromeIEFirefoxSafariOpera<s>YesYesYesYesYes 所有浏览器都支持 <s> 标签。 定义和用法 <s> 标签可定义加…...
微信小程序 - scroll-view组件之上拉加载下拉刷新(解决上拉加载不触发)
前言 最近在做微信小程序项目中,有一个功能就是做一个商品列表分页限流然后实现上拉加载下拉刷新功能,遇到了一个使用scroll-viwe组件下拉刷新事件始终不触发问题,网上很多说给scroll-view设置一个高度啥的就可以解决,有些人设置了…...
rust usize与i64怎么比较大小?
在Rust中, usize 和 i64 是不同的整数类型,它们的位数和表示范围可能不同。因此,直接比较 usize 和 i64 是不允许的。如果需要比较它们的大小,可以将它们转换为相同的类型,然后进行比较。 要将 usize 转换为 i64 &…...
电脑更新win10黑屏解决方法
电脑更新win10黑屏解决方法 电脑黑屏出现原因解决步骤 彻底解决 电脑黑屏 出现原因 系统未更新成功就关机,导致系统出故障无法关机 解决步骤 首先长安电源键10s关机 按电源键开机,出现logo时按F8进入安全模式。 进入自动修复环境后,单击…...
STM32入门——外部中断
中断系统概述 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行中断优先级ÿ…...
【计算机网络】NAT及Bridge介绍
OSI七层模型 七层模型介绍及举例 为通过网络将人类可读信息通过网络从一台设备传输到另一台设备,必须在发送设备沿 OSI 模型的七层结构向下传输数据,然后在接收端沿七层结构向上传输数据。 数据在 OSI 模型中如何流动 库珀先生想给帕尔梅女士发一封电…...
封装动态SQL的插件
最近根据公司的业务需要封装了一个简单的动态SQL的插件,要求是允许用户在页面添加SQL的where条件,然后开发者只需要给某个接口写查询对应的表,参数全部由插件进行拼接完成。下面是最终实现: 开发人员只需要在接口写上下面的查询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:设置批次大小,默认16klinger.ms:设置等待时间,修改为5-100msbuffer.memory:设置缓冲区大小, 默认…...
js精度丢失的问题
1.js精度丢失的常见问题,从常见的浮点型进行计算,到位数很长的munber类型进行计算都会造成精度丢失的问题, 首先我们看一个问题: 0.1 0.2 ! 0.3 // truelet a 9007199254740992 a 1 a // true那么js为什么会出现精度丢失的问题&…...
C++ 编译预处理
在编译器对源程序进行编译时,首先要由处理器对程序文本进行预处理。预处理器提供了一组编译预处理指令和预处理操作符。预处理指令实际上不是C语言的一部分,它只是用来扩充C程序设计环境。所有的预处理指令在程序中都以“#”来引导,每一条预处…...
备战秋招 | 笔试强化22
目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、在有序双向链表中定位删除一个元素的平均时间复杂度为 A. O(1) B. O(N) C. O(logN) D. O(N*logN) 2、在一个以 h 为头指针的单循环链表中,p 指针指向链尾结点的条件是( ) A. p->ne…...
LeetCode ACM模式——哈希表篇(二)
刷题顺序及思路来源于代码随想录,网站地址:https://programmercarl.com 202. 快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复…...
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…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...
GB/T 43887-2024 核级柔性石墨板材检测
核级柔性石墨板材是指以可膨胀石墨为原料、未经改性和增强、用于核工业的核级柔性石墨板材。 GB/T 43887-2024核级柔性石墨板材检测检测指标: 测试项目 测试标准 外观 GB/T 43887 尺寸偏差 GB/T 43887 化学成分 GB/T 43887 密度偏差 GB/T 43887 拉伸强度…...
基于谷歌ADK的 智能产品推荐系统(2): 模块功能详解
在我的上一篇博客:基于谷歌ADK的 智能产品推荐系统(1): 功能简介-CSDN博客 中我们介绍了个性化购物 Agent 项目,该项目展示了一个强大的框架,旨在模拟和实现在线购物环境中的智能导购。它不仅仅是一个简单的聊天机器人,更是一个集…...
