Go-Zero 框架使用 MongoDB,数据采集入库如此简单

目录

引言

环境准备

如何使用

main入口代码实现

实现采集网络接口

总结

其他资源


引言

Go-Zero 是一个高性能、可扩展的微服务框架,专为 Go 语言设计。它提供了丰富的功能,如 RPC、RESTful API 支持、服务发现、熔断器、限流器等,使开发者能够快速构建分布式系统。在众多数据存储选项中,MongoDB 作为一种流行的 NoSQL 数据库,以其灵活性和高性能受到广泛欢迎。本文将介绍如何在 Go-Zero 项目中集成 MongoDB,来看下借助go-zero的goctl工具,实现golang采集网络数据入MongoDB库是多么的简单。

这里以一个小目标任务为例:

采集知乎日报每天的日报数据入MongoDB库(注:仅用于个人学习研究目的,禁止用于其它用途),详细介绍下 Go-Zero 框架集成 MongoDB 数据库的使用。

顺便推荐下go-zero微服务框架,即强大又好用。不但用于微服务,它里面的各个模块也是可以独立拿来用。这里的小任务(采集数据入mongo库),没有使用go-zero的微服务,仅使用了它里面的logx日志模块、httpc客户端模块,config配置文件操作模块和goctl自动化生成 MongoDB的model层代码。

环境准备

goctl:确保你已经安装了 Go-Zero的goctl命令行工具。goctl 是 go-zero 的内置脚手架,是提升开发效率的一大利器,可以一键生成代码、文档、部署 k8s yaml、dockerfile 等。

$ go install github.com/zeromicro/go-zero/tools/goctl@latest

或者手动下载安装:

goctl 安装 | go-zero Documentation

MongoDB:在本地或远程服务器上安装并运行 MongoDB 实例。

MongoDB: The Developer Data Platform | MongoDB

Go:安装最新版本的 Go 语言环境。

https://go.dev/dl/

如何使用

goctl model 为 goctl 提供的数据库模型代码生成指令,目前支持 MySQL、PostgreSQL、Mongo 的代码生成,MySQL 支持从 sql 文件和数据库连接两种方式生成。

Mongo 模型层代码的生成不同于 MySQL,MySQL 可以从 scheme_information 库中读取到一张表的信息(字段名称,数据类型,索引等), 而 Mongo 是文档型数据库,我们暂时无法从 db 中读取某一条记录来实现字段信息获取。

新建一项目目录文件夹,假设为collect。

#进入项目根目录
cd collect
#开始生成
goctl model mongo -t ZhiNews -dir model/zhiNews

各个参数的含义,主要用的是 -t -e -dir

-t是生成文件的前缀名称

-e表示的是生成一个简单的增删改查接口,-dir是生成文档放在的目录

-c是带缓存的 

生成model层代码执行以上命令即可。很简单,不需要提前编写什么模型文件,以上命令将自动在model/zhiNews目录下生成模型框架代码,如果需要扩展其他字段类型,直接修改生成的zhinewstypes.go文件。

zhinewsmodelgen.go 

这个文件是自动生成的,不要修改。

// Code generated by goctl. DO NOT EDIT.
package modelimport ("context""time""github.com/zeromicro/go-zero/core/stores/mon""go.mongodb.org/mongo-driver/bson""go.mongodb.org/mongo-driver/bson/primitive""go.mongodb.org/mongo-driver/mongo"
)type zhiNewsModel interface {Insert(ctx context.Context, data *ZhiNews) errorFindOne(ctx context.Context, id string) (*ZhiNews, error)Update(ctx context.Context, data *ZhiNews) (*mongo.UpdateResult, error)Delete(ctx context.Context, id string) (int64, error)
}type defaultZhiNewsModel struct {conn *mon.Model
}func newDefaultZhiNewsModel(conn *mon.Model) *defaultZhiNewsModel {return &defaultZhiNewsModel{conn: conn}
}func (m *defaultZhiNewsModel) Insert(ctx context.Context, data *ZhiNews) error {if data.ID.IsZero() {data.ID = primitive.NewObjectID()data.CreateAt = time.Now()data.UpdateAt = time.Now()}_, err := m.conn.InsertOne(ctx, data)return err
}func (m *defaultZhiNewsModel) FindOne(ctx context.Context, id string) (*ZhiNews, error) {oid, err := primitive.ObjectIDFromHex(id)if err != nil {return nil, ErrInvalidObjectId}var data ZhiNewserr = m.conn.FindOne(ctx, &data, bson.M{"_id": oid})switch err {case nil:return &data, nilcase mon.ErrNotFound:return nil, ErrNotFounddefault:return nil, err}
}func (m *defaultZhiNewsModel) Update(ctx context.Context, data *ZhiNews) (*mongo.UpdateResult, error) {data.UpdateAt = time.Now()res, err := m.conn.UpdateOne(ctx, bson.M{"_id": data.ID}, bson.M{"$set": data})return res, err
}func (m *defaultZhiNewsModel) Delete(ctx context.Context, id string) (int64, error) {oid, err := primitive.ObjectIDFromHex(id)if err != nil {return 0, ErrInvalidObjectId}res, err := m.conn.DeleteOne(ctx, bson.M{"_id": oid})return res, err
}

zhinewstypes.go

在这个文件里根据需要扩展类型字段。

package modelimport ("time""go.mongodb.org/mongo-driver/bson/primitive"
)type Stories struct {Title  string `bson:"title" json:"title"`Url    string `bson:"url" json:"url"`Hint   string `bson:"hint" json:"hint"`Images string `bson:"images" json:"images"`Id     int64  `bson:"id" json:"id"`
}type TopStories struct {Title  string `bson:"title" json:"title"`Url    string `bson:"url" json:"url"`Hint   string `bson:"hint" json:"hint"`Images string `bson:"images" json:"images"`Id     int64  `bson:"id" json:"id"`
}type ZhiNews struct {ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`// TODO: Fill your own fieldsDate      string       `bson:"date" json:"date"`Storys    []Stories    `bson:"stories" json:"stories"`TopStorys []TopStories `bson:"top_stories" json:"top_stories"`UpdateAt  time.Time    `bson:"updateAt,omitempty" json:"updateAt,omitempty"`CreateAt  time.Time    `bson:"createAt,omitempty" json:"createAt,omitempty"`
}

 zhinewsmodel.go

注意,那个zhinewsmodelgen.go,文件后带gen的文件是自动生成的,默认提供的接口实现,但肯定不够用,但也不要在这里编辑。可以在zhinewsmodel.go文件中扩展实现

如下所示:

package modelimport ("context""time""github.com/zeromicro/go-zero/core/stores/mon""go.mongodb.org/mongo-driver/bson""go.mongodb.org/mongo-driver/mongo"
)var _ ZhiNewsModel = (*customZhiNewsModel)(nil)type (// ZhiNewsModel is an interface to be customized, add more methods here,// and implement the added methods in customZhiNewsModel.ZhiNewsModel interface {zhiNewsModel// 增加 插入重复则更新InsertWithUpdate(ctx context.Context, data *ZhiNews) error// 增加 根据日期来更新UpdateOneByDate(ctx context.Context, data *ZhiNews) (*mongo.UpdateResult, error)// 增加 根据日期查找FindOneByDate(ctx context.Context, date string) (*ZhiNews, error)}customZhiNewsModel struct {*defaultZhiNewsModel}
)// NewZhiNewsModel returns a model for the mongo.
func NewZhiNewsModel(url, db, collection string) ZhiNewsModel {conn := mon.MustNewModel(url, db, collection)return &customZhiNewsModel{defaultZhiNewsModel: newDefaultZhiNewsModel(conn),}
}func (m *customZhiNewsModel) InsertWithUpdate(ctx context.Context, data *ZhiNews) error {err := m.Insert(ctx, data)if mongo.IsDuplicateKeyError(err) {_, err = m.UpdateOneByDate(ctx, data)}return err
}func (m *customZhiNewsModel) UpdateOneByDate(ctx context.Context, data *ZhiNews) (*mongo.UpdateResult, error) {dat, err := m.FindOneByDate(ctx, data.Date)if err != nil {return nil, err}data.ID = dat.IDdata.UpdateAt = time.Now()res, err := m.conn.UpdateOne(ctx, bson.M{"_id": data.ID}, bson.M{"$set": data})return res, err
}func (m *customZhiNewsModel) FindOneByDate(ctx context.Context, date string) (*ZhiNews, error) {var data ZhiNewserr := m.conn.FindOne(ctx, &data, bson.M{"date": date})switch err {case nil:return &data, nilcase mon.ErrNotFound:return nil, ErrNotFounddefault:return nil, err}
}

config.yaml:

MongoDB:Url: "mongodb://test1:xxxx@175.xxx.126.10:27017/?tls=false&authSource=test1"DbName: "test1"Collection: "zhiNews"

main入口代码实现

package mainimport (model "collect/model/zhiNews""context""encoding/json""errors""flag""fmt""io""net/http""time""github.com/tidwall/gjson""github.com/zeromicro/go-zero/core/conf"log "github.com/zeromicro/go-zero/core/logx""github.com/zeromicro/go-zero/rest/httpc"
)type Config struct {MongoDB struct {Url        string `json:",default=mongodb://localhost:27017"`DbName     string `json:",default=testdb"`Collection string `json:",default=zhiNews"`}
}var f = flag.String("f", "etc/config.yaml", "config file")func getZhiNews(date string) (resp *model.ZhiNews, err error) {url := "https://news-at.zhihu.com/api/4/news/latest"parsedDate, err := time.Parse("20060102", date)if err != nil {log.Errorf("Error parsing date:%s", err)}now := time.Now().Format("20060102")if now != date {url = "https://news-at.zhihu.com/api/4/news/before/" + parsedDate.AddDate(0, 0, 1).Format("20060102")}// 创建一个请求r, err := http.NewRequest("GET", url, nil)if err != nil {log.Error(err)return nil, err}//设置常见的HTTP头r.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3")//ctx := context.Background()//res, err_ := httpc.Do(ctx, http.MethodGet, url, nil)res, err_ := httpc.DoRequest(r)if err_ != nil {log.Error(err_)return nil, err}defer res.Body.Close()body, err := io.ReadAll(res.Body)if err != nil {log.Errorf("Failed to read response body:%s", err)return nil, err}log.Debug(res.StatusCode)var keyVal map[string]interface{}err = json.Unmarshal(body, &keyVal)if err != nil {log.Errorf("Failed to extract key value:%s", err)}//log.Debugf("keyVal:%v", keyVal)if res.StatusCode != 200 {log.Errorf("Failed to request,%s", res.Status)return nil, errors.New(res.Status)}var zhi model.Storiesvar responseData []model.Storieslist_ := gjson.GetBytes(body, "stories").Array()for _, item := range list_ {zhi.Id = item.Get("id").Int()zhi.Title = item.Get("title").String()zhi.Images = item.Get("images.0").String()zhi.Url = item.Get("url").String()zhi.Hint = item.Get("hint").String()responseData = append(responseData, zhi)}var top model.TopStoriesvar topData []model.TopStorieslist_1 := gjson.GetBytes(body, "top_stories").Array()for _, item := range list_1 {top.Id = item.Get("id").Int()top.Title = item.Get("title").String()top.Images = item.Get("images.0").String()top.Url = item.Get("url").String()top.Hint = item.Get("hint").String()topData = append(topData, top)}log.Debugf("len list_:%d", len(list_))if len(list_) != 0 {resp = &model.ZhiNews{Storys:    responseData,TopStorys: topData,Date:      gjson.GetBytes(body, "date").String(),}} else {resp = &model.ZhiNews{Storys:    nil,TopStorys: nil,Date:      date,}}return resp, nil
}func main() {fmt.Printf("collect: %s\n", "start")flag.Parse()var c Configconf.MustLoad(*f, &c)log.Info("config: ", c)mo := model.NewZhiNewsModel(c.MongoDB.Url, c.MongoDB.DbName, c.MongoDB.Collection)ctx := context.Background()// 获取今天的日期today := time.Now()// 设置采集的天数范围daysAgo := 49 // 例如,采集从今天往前的7天数据for i := 0; i < daysAgo; i++ {date := today.AddDate(0, 0, -i).Format("20060102")log.Info("date: ", date)resp, err := getZhiNews(date)if err != nil {log.Errorf("getZhiNews error:" + err.Error())return}err = mo.InsertWithUpdate(ctx, resp)if err != nil {log.Errorf("InsertWithUpdate error: %v", err)return}log.Info("getZhiNews Insert ok")}fmt.Printf("collect: %s\n", "end")
}

注意,直接使用httpc模块的do方法,可能会被后台认为是机器人操作而直接返回403错误。

//ctx := context.Background()
//res, err_ := httpc.Do(ctx, http.MethodGet, url, nil)

这里使用其支持自定义http报文头的写法:

    // 创建一个请求r, err := http.NewRequest("GET", url, nil)if err != nil {log.Error(err)return nil, err}//设置常见的HTTP头r.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3")//ctx := context.Background()//res, err_ := httpc.Do(ctx, http.MethodGet, url, nil)res, err_ := httpc.DoRequest(r)if err_ != nil {log.Error(err_)return nil, err}defer res.Body.Close()body, err := io.ReadAll(res.Body)if err != nil {log.Errorf("Failed to read response body:%s", err)return nil, err}log.Debug(res.StatusCode)

model层的代码使用

package mainimport (model "collect/model/zhiNews""context""errors""flag""fmt""io""net/http""time""github.com/tidwall/gjson""github.com/zeromicro/go-zero/core/conf"log "github.com/zeromicro/go-zero/core/logx""github.com/zeromicro/go-zero/rest/httpc"
)func main() {fmt.Printf("collect: %s\n", "start")flag.Parse()var c Configconf.MustLoad(*f, &c)log.Info("config: ", c)//mo := model.NewZhiNewsModel("mongodb://test1:psdddd@localhost:27017/?tls=false&authSource=test1", "test1", "zhiNews")//model的使用mo := model.NewZhiNewsModel(c.MongoDB.Url, c.MongoDB.DbName, c.MongoDB.Collection)ctx := context.Background()......
}

实现采集网络接口

知乎日报接口:

#获取最新每日一报
get https://news-at.zhihu.com/api/4/news/latest###历史日报
get https://news-at.zhihu.com/api/4/news/before/20240617#curl访问
curl -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3" https://news-at.zhihu.com/api/4/news/before/20240622
func getZhiNews(date string) (resp *model.ZhiNews, err error) {url := "https://news-at.zhihu.com/api/4/news/latest"parsedDate, err := time.Parse("20060102", date)if err != nil {log.Errorf("Error parsing date:%s", err)}now := time.Now().Format("20060102")if now != date {url = "https://news-at.zhihu.com/api/4/news/before/" + parsedDate.AddDate(0, 0, 1).Format("20060102")}// 创建一个请求r, err := http.NewRequest("GET", url, nil)if err != nil {log.Error(err)return nil, err}//设置常见的HTTP头r.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3")//ctx := context.Background()//res, err_ := httpc.Do(ctx, http.MethodGet, url, nil)res, err_ := httpc.DoRequest(r)if err_ != nil {log.Error(err_)return nil, err}defer res.Body.Close()body, err := io.ReadAll(res.Body)if err != nil {log.Errorf("Failed to read response body:%s", err)return nil, err}log.Debug(res.StatusCode)var keyVal map[string]interface{}err = json.Unmarshal(body, &keyVal)if err != nil {log.Errorf("Failed to extract key value:%s", err)}//log.Debugf("keyVal:%v", keyVal)if res.StatusCode != 200 {log.Errorf("Failed to request,%s", res.Status)return nil, errors.New(res.Status)}var zhi model.Storiesvar responseData []model.Storieslist_ := gjson.GetBytes(body, "stories").Array()for _, item := range list_ {zhi.Id = item.Get("id").Int()zhi.Title = item.Get("title").String()zhi.Images = item.Get("images.0").String()zhi.Url = item.Get("url").String()zhi.Hint = item.Get("hint").String()responseData = append(responseData, zhi)}var top model.TopStoriesvar topData []model.TopStorieslist_1 := gjson.GetBytes(body, "top_stories").Array()for _, item := range list_1 {top.Id = item.Get("id").Int()top.Title = item.Get("title").String()top.Images = item.Get("images.0").String()top.Url = item.Get("url").String()top.Hint = item.Get("hint").String()topData = append(topData, top)}log.Debugf("len list_:%d", len(list_))if len(list_) != 0 {resp = &model.ZhiNews{Storys:    responseData,TopStorys: topData,Date:      gjson.GetBytes(body, "date").String(),}} else {resp = &model.ZhiNews{Storys:    nil,TopStorys: nil,Date:      date,}}return resp, nil
}

设置采集的天数范围,开始采集

   // 获取今天的日期today := time.Now()// 设置采集的天数范围daysAgo := 49 // 例如,采集从今天往前的49天数据for i := 0; i < daysAgo; i++ {date := today.AddDate(0, 0, -i).Format("20060102")log.Info("date: ", date)resp, err := getZhiNews(date)if err != nil {log.Errorf("getZhiNews error:" + err.Error())return}err = mo.InsertWithUpdate(ctx, resp)if err != nil {log.Errorf("InsertWithUpdate error: %v", err)return}log.Info("getZhiNews Insert ok")}

总结

以上完成实现了采集知乎日报的新闻列表信息,采集入mongoDB数据库。使用了go-zero 的goctl工具自动生成操作mongoDB的代码,使用了go-zero框架中的部分模块如日志模块,配置文件操作模块、网络访问模块等。可以看到借助goctl自动生成代码,采集数据入mongoDB数据库是多么的简单方便。再次推荐下go-zero这一优秀的微服务框架。

其他资源

配置文件 | go-zero Documentation

goctl model | go-zero Documentation

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyQt5显示QImage并将QImage转换为PIL图像保存到缓存

PyQt5显示QImage并将QImage转换为PIL图像保存到缓存 1、效果图 2、流程 1、获取摄像头资源,打开摄像头 2、截取图像 3、opencv读的通道是BGR,要转成RGB 4、往显示视频的Label里显示QImage 5、将QImage转换为PIL图像,并保存到缓存 6、获取图像中人脸信息3、代码 # -*- codin…

2024年【安全员-C证】考试及安全员-C证免费试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 安全员-C证考试根据新安全员-C证考试大纲要求&#xff0c;安全生产模拟考试一点通将安全员-C证模拟考试试题进行汇编&#xff0c;组成一套安全员-C证全真模拟考试试题&#xff0c;学员可通过安全员-C证免费试题全真模…

论文解析——Full Stack Optimization of Transformer Inference: a Survey

作者及发刊详情 摘要 正文 主要工作贡献 这篇文章的贡献主要有两部分&#xff1a; 分析Transformer的特征&#xff0c;调查高效transformer推理的方法通过应用方法学展现一个DNN加速器生成器Gemmini的case研究 1&#xff09;分析和解析Transformer架构的运行时特性和瓶颈…

堆叠的作用

一、为什么要堆叠 传统的园区网络采用设备和链路冗余来保证高可靠性&#xff0c;但其链路利用率低、网络维护成本高&#xff0c;堆叠技术将多台交换机虚拟成一台交换机&#xff0c;达到简化网络部署和降低网络维护工作量的目的。 二、堆叠优势 1、提高可靠性 堆叠系统多台成…

Linux--线程(概念篇)

目录 1.背景知识 再谈地址空间&#xff1a; 关于页表&#xff08;32bit机器上&#xff09; 2.线程的概念和Linux中线程的实现 概念部分&#xff1a; 代码部分&#xff1a; 问题&#xff1a; 3.关于线程的有点与缺点 4.进程VS线程 1.背景知识 再谈地址空间&#xff1a…

Linux中的粘滞位及mysql日期函数

只要用户具有目录的写权限, 用户就可以删除目录中的文件, 而不论这个用户是否有这个文件的写 权限. 为了解决这个不科学的问题, Linux引入了粘滞位的概念. 粘滞位 当一个目录被设置为"粘滞位"(用chmod t),则该目录下的文件只能由 一、超级管理员删除 二、该目录…

FreeRTOS 列表和列表项

这里推荐看完韦东山的C语言本质和韦东山的rtos快速入门视频 在 FreeRTOS 的源码中大量地使用了列表和列表项&#xff0c;因此想要深入学习 FreeRTOS&#xff0c;列表和 列表项是必备的基础知识。这里所说的列表和列表项&#xff0c;是 FreeRTOS 源码中 List 和 List Item 的 直…

高创新 | CEEMDAN-VMD-GRU-Attention双重分解+门控循环单元+注意力机制多元时间序列预测

目录 效果一览基本介绍模型设计程序设计参考资料 效果一览 基本介绍 高创新 | CEEMDAN-VMD-GRU-Attention双重分解门控循环单元注意力机制多元时间序列预测 本文提出一种基于CEEMDAN 的二次分解方法&#xff0c;通过样本熵重构CEEMDAN 分解后的序列&#xff0c;复杂序列通过VMD…

Redhat 安装 docker 网络连接超时问题

目录 添加阿里云的Docker CE仓库 更新YUM缓存 安装 Docker Engine 启动并设置Docker自启动 验证 Docker 安装 [userlocalhost ~]$ sudo yum-config-manager --add-repohttps://download.docker.com/linux/centos/docker-ce.repo 正在更新 Subscription Management 软件仓库…

Linux安装Jmeter及简单使用教程

Linux安装Jmeter 首先需要java环境 java --version官网 下载二进制包 #创建文件夹 sudo mkdir /usr/local/jmeter #解压 sudo tar zxvf apache-jmeter-5.6.3.tgz -C /usr/local/jmeter编辑配置文件 sudo vim /etc/profile&#xff0c;添加以下内容 export JMETER_HOME/usr/l…

Linux环境部署Python Web服务

“姑娘&#xff0c;再见面就要靠运气了&#xff0c;可别装作不认识&#xff0c;那句“好久不见”可干万别打颤…” 将使用 Python 编写的后端 API 部署到 Linux 环境中&#xff0c;可以按照以下详细步骤操作。本文将涵盖环境准备、API 编写、使用 Gunicorn 作为 WSGI 服务器、配…

1-3分钟爆款视频素材在哪找啊?这9个热门爆款素材网站分享给你

在如今快节奏的时代&#xff0c;短视频已成为吸引观众注意力的黄金手段。然而&#xff0c;要制作出1-3分钟的爆款视频&#xff0c;除了创意和剪辑技巧外&#xff0c;选择合适的素材至关重要。那么&#xff0c;哪里可以找到那些能让你的视频脱颖而出的爆款素材呢&#xff1f;不用…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【加解密(ArkTS)】

加解密(ArkTS) 以AES 128密钥为例&#xff0c;完成加解密。具体的场景介绍及支持的算法规格。 开发步骤 生成密钥 指定密钥别名。初始化密钥属性集。调用[generateKeyItem]生成密钥&#xff0c;具体请参考[密钥生成]。开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/l…

yolov8-seg分割模型TensorRt部署,去掉torch

已完成的yolov8-seg分割模型TensorRt部署 准备下载yolov8-seg模型转化为onnx和trt推理写好的推理接口 准备 https://github.com/songjiahao-wq/yolov8_seg_trtinference.git下载代码 安装TensorRt8.6版本&#xff0c;以及pip install -r requirements.txt 下载yolov8-seg模型…

【web APIs】快速上手Day05(Bom操作)

目录 Web APIs - 第5天笔记js组成window对象BOM定时器-延迟函数案例-5秒钟之后消失的广告 JS执行机制location对象案例-5秒钟之后跳转的页面 navigator对象histroy对象 本地存储&#xff08;今日重点&#xff09;localStorage&#xff08;重点&#xff09;sessionStorage&#…

三、mysql-万字长文读懂mysql

mysql 三、 Mysql3.1 基础3.1.1 mysql执行流程-组成架构3.2 索引3.2.1 索引底层的数据结构与算法分类在创建表时,InnoDB 存储引擎会根据不同的场景选择不同的列作为索引B+树结构3.2.2 为什么 MySQL InnoDB 选择 B+tree 作为索引的数据结构3.2.2.1. 从磁盘角度出发3.2.2.2. 数据…

深度解析移动硬盘“函数不正确”错误及高效恢复策略

在数据密集型的社会中&#xff0c;移动硬盘作为移动存储的重要载体&#xff0c;承载着无数用户的个人信息、工作资料及珍贵回忆。然而&#xff0c;当遭遇“函数不正确”的错误时&#xff0c;这些宝贵的数据仿佛被一层无形的屏障所阻隔&#xff0c;让人束手无策。本文将深入探讨…

如何选择高性价比的土壤检测仪器?

在现代农业与环保领域&#xff0c;土壤检测仪器的选择显得尤为关键。它不仅关系到土壤养分管理、作物健康生长&#xff0c;还涉及到环境保护和可持续发展。那么&#xff0c;面对市场上琳琅满目的土壤检测仪器&#xff0c;我们该如何选择一款实用的设备呢&#xff1f; 首先&…

(1)滑动窗口算法介绍与练习:长度最小的子数组

滑动窗口算法介绍 所谓滑动窗口&#xff0c;即为同向双指针移动过程中形成的间隔区域&#xff0c;并且这两个指针在移动的过程中不会回退 对于滑动窗口的题目可以抽象为三个步骤&#xff1a; 定义窗口两端指针left和right进入窗口判断离开窗口循环2、3和4步 滑动窗口练习 长度最…

短视频电商源码的优势及软件架构解析

短视频电商源码是目前电商行业中非常火热的一个新兴领域&#xff0c;它通过短视频内容和电商商品的结合&#xff0c;为用户提供了一种新的购物体验。下面将介绍短视频电商源码的优势以及软件架构。 首先&#xff0c;短视频电商源码具有以下几个优势&#xff1a; 1、创新的购物体…