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

playwright-go实战:自动化登录测试

1.新建项目

打开Goland新建项目playwright-go-demo

项目初始化完成后打开终端输入命令:

#安装项目依赖
go get -u github.com/playwright-community/playwright-go
#安装浏览器
go run github.com/playwright-community/playwright-go/cmd/playwright@latest install --with-deps

2.编写代码

项目结构

部分代码

config.go

package configimport ("encoding/json""fmt""os""path/filepath"
)// BrowserConfig 浏览器配置
type BrowserConfig struct {Type      string `json:"type"`      // 浏览器类型:chromium, firefox, webkitHeadless  bool   `json:"headless"`  // 是否无头模式SlowMo    int    `json:"slowMo"`    // 慢动作模式,毫秒Maximized bool   `json:"maximized"` // 是否最大化
}// LoginConfig 登录配置
type LoginConfig struct {Username        string `json:"username"`         // 用户名Password        string `json:"password"`         // 密码URL             string `json:"url"`              // 登录URLInvalidUsername string `json:"invalid_username"` // 无效用户名InvalidPassword string `json:"invalid_password"` // 无效密码
}// Config 应用配置
type Config struct {Browsers []BrowserConfig `json:"browsers"` // 多浏览器配置Login    LoginConfig     `json:"login"`    // 登录配置
}// DefaultConfig 默认配置
var DefaultConfig = Config{Browsers: []BrowserConfig{{Type:      "chromium",Headless:  false,SlowMo:    0,Maximized: true,},{Type:      "webkit",Headless:  false,SlowMo:    0,Maximized: true,},},Login: LoginConfig{Username:        "tomsmith",Password:        "SuperSecretPassword!",URL:             "http://the-internet.herokuapp.com/login",InvalidUsername: "invaliduser",InvalidPassword: "invalidpass",},
}// LoadConfig 从文件加载配置
func LoadConfig(configPath string) (*Config, error) {// 如果配置文件不存在,创建默认配置文件if _, err := os.Stat(configPath); os.IsNotExist(err) {// 确保目录存在dir := filepath.Dir(configPath)if err := os.MkdirAll(dir, 0755); err != nil {return nil, fmt.Errorf("无法创建配置目录: %w", err)}// 写入默认配置file, err := os.Create(configPath)if err != nil {return nil, fmt.Errorf("无法创建配置文件: %w", err)}defer file.Close()encoder := json.NewEncoder(file)encoder.SetIndent("", "  ")if err := encoder.Encode(DefaultConfig); err != nil {return nil, fmt.Errorf("无法写入默认配置: %w", err)}return &DefaultConfig, nil}// 读取配置文件file, err := os.Open(configPath)if err != nil {return nil, fmt.Errorf("无法打开配置文件: %w", err)}defer file.Close()config := &Config{}if err := json.NewDecoder(file).Decode(config); err != nil {return nil, fmt.Errorf("无法解析配置文件: %w", err)}return config, nil
}

config.json

{"browsers": [{"type": "chromium","headless": true,"slowMo": 0,"maximized": true},{"type": "webkit","headless": true,"slowMo": 0,"maximized": true}],"login": {"username": "tomsmith","password": "SuperSecretPassword!","url": "http://the-internet.herokuapp.com/login","invalid_username": "invaliduser","invalid_password": "invalidpass"}
}

pages/login_page.go

package pagesimport ("fmt""github.com/playwright-community/playwright-go"
)// LoginPage 表示登录页面对象
type LoginPage struct {page     playwright.PageloginURL string
}// NewLoginPage 创建一个新的登录页面对象
func NewLoginPage(page playwright.Page) *LoginPage {return &LoginPage{page:     page,loginURL: "http://the-internet.herokuapp.com/login", // 默认URL,将被配置文件中的URL覆盖}
}// SetLoginURL 设置登录URL
func (l *LoginPage) SetLoginURL(url string) {l.loginURL = url
}// Navigate 导航到登录页面
func (l *LoginPage) Navigate() error {_, err := l.page.Goto(l.loginURL, playwright.PageGotoOptions{WaitUntil: playwright.WaitUntilStateNetworkidle,})return err
}// Login 执行登录操作
func (l *LoginPage) Login(username, password string) error {// 输入用户名if err := l.page.Fill("#username", username); err != nil {return fmt.Errorf("无法输入用户名: %w", err)}// 输入密码if err := l.page.Fill("#password", password); err != nil {return fmt.Errorf("无法输入密码: %w", err)}// 点击登录按钮if err := l.page.Click("button[type=\"submit\"]"); err != nil {return fmt.Errorf("无法点击登录按钮: %w", err)}// 等待页面加载完成if err := l.page.WaitForLoadState(playwright.PageWaitForLoadStateOptions{State: playwright.LoadStateNetworkidle,}); err != nil {return fmt.Errorf("等待页面加载超时: %w", err)}return nil
}// VerifyLoginSuccess 验证登录是否成功
func (l *LoginPage) VerifyLoginSuccess() (bool, error) {// 等待成功消息出现successLocator := l.page.Locator(".flash.success")if err := successLocator.WaitFor(playwright.LocatorWaitForOptions{Timeout: playwright.Float(5000),}); err != nil {return false, fmt.Errorf("未找到成功消息: %w", err)}// 检查是否存在登出按钮logoutButton, err := l.page.IsVisible("a[href=\"/logout\"]")if err != nil {return false, fmt.Errorf("检查登出按钮失败: %w", err)}return logoutButton, nil
}// Logout 执行登出操作
func (l *LoginPage) Logout() error {// 点击登出按钮if err := l.page.Click("a[href=\"/logout\"]"); err != nil {return fmt.Errorf("无法点击登出按钮: %w", err)}// 等待页面加载完成if err := l.page.WaitForLoadState(playwright.PageWaitForLoadStateOptions{State: playwright.LoadStateNetworkidle,}); err != nil {return fmt.Errorf("等待页面加载超时: %w", err)}return nil
}// WaitForTimeout 等待指定时间
func (l *LoginPage) WaitForTimeout(ms int) {l.page.WaitForTimeout(float64(ms))
}// VerifyLoginFailed 验证登录失败场景
func (l *LoginPage) VerifyLoginFailed() (bool, error) {// 等待错误消息出现errorLocator := l.page.Locator(".flash.error")if err := errorLocator.WaitFor(playwright.LocatorWaitForOptions{Timeout: playwright.Float(5000),}); err != nil {return false, fmt.Errorf("未找到错误消息: %w", err)}// 检查是否仍在登录页面(通过登录按钮是否可见来判断)loginButton, err := l.page.IsVisible("button[type=\"submit\"]")if err != nil {return false, fmt.Errorf("检查登录按钮失败: %w", err)}return loginButton, nil
}

main.go

package mainimport ("fmt""log""os""path/filepath""time""github.com/playwright-community/playwright-go""github.com/wan/playwright-go-demo/config""github.com/wan/playwright-go-demo/pages""github.com/wan/playwright-go-demo/utils"
)func main() {// 清理旧的测试结果if err := utils.CleanupOldTestResults(); err != nil {log.Printf("警告: 清理旧测试结果失败: %v", err)}// 加载配置文件configPath := "./config/config.json"cfg, err := config.LoadConfig(configPath)if err != nil {log.Fatalf("加载配置文件失败: %v", err)}// 初始化Playwrightpw, err := playwright.Run()if err != nil {log.Fatalf("无法启动Playwright: %v", err)}defer pw.Stop()// 确保截图目录存在screenshotDir := "./screenshots"if _, err := os.Stat(screenshotDir); os.IsNotExist(err) {os.MkdirAll(screenshotDir, 0755)}// 确保视频目录存在videoDir := "./videos"if _, err := os.Stat(videoDir); os.IsNotExist(err) {os.MkdirAll(videoDir, 0755)}// 遍历所有配置的浏览器,分别执行测试for _, browserConfig := range cfg.Browsers {// 为每个浏览器创建单独的测试报告reportManager := utils.NewReportManager(fmt.Sprintf("%s浏览器登录测试", browserConfig.Type))// 执行特定浏览器的测试runTestWithBrowser(pw, browserConfig, cfg.Login, screenshotDir, videoDir, reportManager)}
}// runTestWithBrowser 使用特定浏览器执行测试
func runTestWithBrowser(pw *playwright.Playwright, browserConfig config.BrowserConfig, loginConfig config.LoginConfig, screenshotDir, videoDir string, reportManager *utils.ReportManager) {// 根据配置选择浏览器类型var browserType playwright.BrowserTypeswitch browserConfig.Type {case "firefox":browserType = pw.Firefoxcase "webkit":browserType = pw.WebKitdefault:browserType = pw.Chromium}fmt.Printf("开始使用 %s 浏览器执行测试\n", browserConfig.Type)// 创建浏览器实例browser, err := browserType.Launch(playwright.BrowserTypeLaunchOptions{Headless: playwright.Bool(browserConfig.Headless),SlowMo:   playwright.Float(float64(browserConfig.SlowMo)),})if err != nil {log.Printf("无法启动 %s 浏览器: %v", browserConfig.Type, err)return}defer browser.Close()// 创建上下文contextOptions := playwright.BrowserNewContextOptions{RecordVideo: &playwright.RecordVideo{Dir: filepath.Join(videoDir, browserConfig.Type), // 为每个浏览器创建单独的视频目录},}// 如果配置了最大化,设置视口大小为最大if browserConfig.Maximized {// 设置一个足够大的视口大小来模拟最大化contextOptions.Viewport = &playwright.Size{Width:  1920,Height: 1080,}}// 确保浏览器特定的视频目录存在browserVideoDir := filepath.Join(videoDir, browserConfig.Type)if _, err := os.Stat(browserVideoDir); os.IsNotExist(err) {os.MkdirAll(browserVideoDir, 0755)}// 确保浏览器特定的截图目录存在browserScreenshotDir := filepath.Join(screenshotDir, browserConfig.Type)if _, err := os.Stat(browserScreenshotDir); os.IsNotExist(err) {os.MkdirAll(browserScreenshotDir, 0755)}context, err := browser.NewContext(contextOptions)if err != nil {log.Printf("无法创建 %s 浏览器上下文: %v", browserConfig.Type, err)return}defer context.Close()// 创建页面page, err := context.NewPage()if err != nil {log.Printf("无法创建 %s 浏览器页面: %v", browserConfig.Type, err)return}reportManager.StartTest("登录测试")// 执行测试testStart := time.Now()try := func() bool {// 创建登录页面对象loginPage := pages.NewLoginPage(page)// 设置登录URLloginPage.SetLoginURL(loginConfig.URL)// 步骤1: 导航到登录页面reportManager.StartStep("导航到登录页面")if err := loginPage.Navigate(); err != nil {// 失败时截图screenshotPath := filepath.Join(browserScreenshotDir, "navigate_failure.png")utils.TakeScreenshot(page, screenshotPath)reportManager.EndStepFailure("导航到登录页面失败", err, screenshotPath)return false}reportManager.EndStepSuccess("成功导航到登录页面")// 测试场景1: 使用错误的用户名登录reportManager.StartStep("测试错误用户名登录")if err := loginPage.Login("wrong_username", loginConfig.Password); err != nil {screenshotPath := filepath.Join(browserScreenshotDir, "wrong_username_input_failure.png")utils.TakeScreenshot(page, screenshotPath)reportManager.EndStepFailure("输入错误用户名失败", err, screenshotPath)return false}if failed, err := loginPage.VerifyLoginFailed(); err != nil || !failed {screenshotPath := filepath.Join(browserScreenshotDir, "wrong_username_verify_failure.png")utils.TakeScreenshot(page, screenshotPath)reportManager.EndStepFailure("验证错误用户名失败场景失败", err, screenshotPath)return false}reportManager.EndStepSuccess("成功验证错误用户名登录失败场景")// 测试场景2: 使用错误的密码登录reportManager.StartStep("测试错误密码登录")if err := loginPage.Login(loginConfig.Username, "wrong_password"); err != nil {screenshotPath := filepath.Join(browserScreenshotDir, "wrong_password_input_failure.png")utils.TakeScreenshot(page, screenshotPath)reportManager.EndStepFailure("输入错误密码失败", err, screenshotPath)return false}if failed, err := loginPage.VerifyLoginFailed(); err != nil || !failed {screenshotPath := filepath.Join(browserScreenshotDir, "wrong_password_verify_failure.png")utils.TakeScreenshot(page, screenshotPath)reportManager.EndStepFailure("验证错误密码失败场景失败", err, screenshotPath)return false}reportManager.EndStepSuccess("成功验证错误密码登录失败场景")// 测试场景3: 使用正确的凭据登录reportManager.StartStep("测试正确凭据登录")if err := loginPage.Login(loginConfig.Username, loginConfig.Password); err != nil {screenshotPath := filepath.Join(browserScreenshotDir, "login_failure.png")utils.TakeScreenshot(page, screenshotPath)reportManager.EndStepFailure("登录失败", err, screenshotPath)return false}if success, err := loginPage.VerifyLoginSuccess(); err != nil || !success {screenshotPath := filepath.Join(browserScreenshotDir, "verification_failure.png")utils.TakeScreenshot(page, screenshotPath)reportManager.EndStepFailure("验证登录失败", err, screenshotPath)return false}reportManager.EndStepSuccess("成功验证正确凭据登录")return true}success := try()testDuration := time.Since(testStart)// 完成测试报告if success {reportManager.LogSuccess("登录测试成功", testDuration)} else {reportManager.LogFailure("登录测试失败", testDuration)}// 生成测试报告reportPath, err := reportManager.GenerateReport()if err != nil {log.Fatalf("生成测试报告失败: %v", err)}fmt.Printf("测试完成,报告已生成: %s\n", reportPath)
}

更多详细代码查看仓库:https://github.com/wan88888/playwright-go-demo

3.运行测试

本地运行

在终端执行命令:

go run main.go

测试报告

远程测试

相关文章:

playwright-go实战:自动化登录测试

1.新建项目 打开Goland新建项目playwright-go-demo 项目初始化完成后打开终端输入命令: #安装项目依赖 go get -u github.com/playwright-community/playwright-go #安装浏览器 go run github.com/playwright-community/playwright-go/cmd/playwrightlatest insta…...

手机扫描仪 含PDF转word功能+OCR识别110种语言

TapScanner Premium 是一款功能强大的手机扫描仪应用,支持 PDF 合并、分割以及转换为 Word 文档格式,还具备 OCR 识别功能,可识别 110 种语言。汉化中文且已激活全部功能,可免费使用。 该应用操作简洁,扫描文档、收据…...

数据可视化在商业智能中的应用:从数据到洞察的桥梁

数据可视化在商业智能中的应用:从数据到洞察的桥梁 大家好,我是Echo_Wish。今天,我们来探讨一个数据领域的热门话题——数据可视化在商业智能中的应用。在数据驱动的时代,如何从海量的数字和信息中提炼出有价值的洞察,成为了企业决策的关键。而数据可视化,正是将枯燥的数…...

【HarmonyOS Next的奇幻大冒险】DevEco Studio的AI助手CodeGenie挺好用

遇到些问题在官网搜不出答案,CodeGenie都给解决了! 不过我的问题可能比较初级,往后再看看它的能力怎么样 下面的截图是关于其中一个问题的对话。可见CodeGenie干脆利索,并且给出了相关知识点在官网上的参考信息链接,大…...

替代-UX设计师

初创公司如何在没有设计师的情况下 打造实用的用户体验 一个常见的捷径是使用预构建的组件库,如谷歌的 Material UI它们为你提供了构建块,但它们并没有为你考虑整个用户流程你仍然需要弄清楚所有这些是如何组合在一起的但是,很多时候&#x…...

ISIS-1 ISIS概述

前面几章我们介绍了OSPF的基础工作原理以及怎样交互LSA形成LSDB链路状态数据库的 这一章我们来介绍另一个链路状态路由协议,ISIS路由协议 一、概述 ISIS(Intermediate System to Intermediate System,中间系统到中间系统)是由ISO(International Organization for Standardiza…...

电脑上不了网普通用户排除方法

1:首先通过电脑的运行/CMD/ipconfig /all 命令查看电脑的ip地址是否正常如图: 2:在命令行中运行:ping 127.0.0.1 如图则正常,否则要重新安装网卡驱动 程序。 3:用ping命令,ping一下同网段的电…...

Qt 控件概述 QLCDNumber 和 Progressbar

目录 QLCDNumber 进度条 定时器进度条的实现 通过stylesheet来改变进度条颜色​ QLCDNumber LCD数字显示器 实现一个定时器 QLCDNumber 进度条 定时器进度条的实现 为什在Widget.h种头文件并没有包含QTimer这个头文件,却还可以申明一个TImer指针呢?…...

2025.03.21首板涨停股票分析

目录 1 涨停原因分析2 交易建议 1 涨停原因分析 2 交易建议...

数据库的DDL操作

目录 一、创建数据库 (1)字符集和校验集 二、操作数据库 (1)查看数据库 (2)显示创建语句 (3)修改数据库 (4)删除数据库 三、数据库的备份与恢复 四、…...

Docker 部署 Graylog 日志管理系统

Docker 部署 Graylog 日志管理系统 前言一、准备工作二、Docker Compose 配置三、启动 Graylog 服务四、访问 Graylog Web 界面总结 前言 Graylog 是一个开源的日志管理平台,专为实时日志收集、分析和可视化设计。它支持强大的搜索功能,并且与 Elastics…...

特征工程自动化(FeatureTools实战)

目录 特征工程自动化(FeatureTools实战)1. 引言2. 项目背景与意义2.1 特征工程的重要性2.2 自动化特征工程的优势2.3 工业级数据处理需求3. 数据集生成与介绍3.1 数据集构成3.2 数据生成方法4. 自动化特征工程理论基础4.1 特征工程的基本概念4.2 FeatureTools库简介4.3 关键公…...

Linux:xxx is not in the sudoers file. This incident will be reported.

报错 xxx is not in the sudoers file. This incident will be reported.解决方式 切换到root用户下操作 # 1、修改/etc/sudoers文件为可修改,默认是只读的 ls -lh /etc/sudoers -r--r----- 1 root root 4.3K Dec 1 01:45 /etc/sudoerschmod uw /etc/sudoersls…...

fastapi+playwright爬取google搜索1-3页的关键词返回json

1,playwright无头 2,代理池随机获取代理ip 3,随机浏览行为,随机页面滚动 4,启用stealth模式 5,随机延时搜索 from fastapi import FastAPI, HTTPException from fastapi.responses import JSONResponse import asyncio from concurrent.futures import ThreadPool…...

论文阅读笔记:Denoising Diffusion Probabilistic Models (3)

论文阅读笔记:Denoising Diffusion Probabilistic Models (1) 论文阅读笔记:Denoising Diffusion Probabilistic Models (2) 论文阅读笔记:Denoising Diffusion Probabilistic Models (3) 4、损失函数逐项分析 可以看出 L L L总共分为了3项…...

FlauBERT:面向法语的无监督语言模型预训练

摘要 语言模型已成为在许多不同自然语言处理(NLP)任务中取得最先进成果的关键步骤。利用当今可用的大量未标注文本,它们提供了一种有效的方式来预训练连续词表示,这些表示可以在下游任务中进行微调,并在句子级别上进行…...

JavaScript严格模式

文章主要介绍JavaScript严格模式,包括启用原因、方式以及需避开的常见陷阱,助力开发者写出更健壮代码。 1. 启用原因:将普通JavaScript中的“静默错误”变为抛出错误,有助于编写健壮代码;修复阻碍JavaScript引擎优化的…...

文件上传的小点总结(1)

2.文件类型绕过 问题插入:BP无法拦截本地流量 ①插件限制 不代理的地址列表通常写有localhost和127.0.0.1,把本地的全都删掉,然后应用保存。 ②浏览器限制 Firefox浏览器设置:检查浏览器代理配置和proxy listeners都没问题后&…...

2024年数维杯数学建模B题生物质和煤共热解问题的研究解题全过程论文及程序

2024年数维杯数学建模 B题 生物质和煤共热解问题的研究 原题再现: 随着全球能源需求的不断增长和对可再生能源的追求,生物质和煤共热解作为一种潜在的能源转化技术备受关注。生物质是指可再生能源,源自植物和动物的有机物质,而煤…...

@maptalks/gl-layers中的VectorTileLayer的Symbol样式文档

maptalks/gl-layers中的VectorTileLayer的Symbol样式文档 矢量的Symbol样式分为以下几个大类: marker样式属性,定义了图标相关样式属性 text样式属性,定义了文字相关样式属性 line样式属性,定义了线相关的样式属性 polygon样式属…...

OpenCV旋转估计(3)帮助构建一个最大生成树(Maximum Spanning Tree)函数findMaxSpanningTree()

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::detail::findMaxSpanningTree 是 OpenCV 中用于图像拼接工作流的一个函数,它帮助构建一个最大生成树(Maximum Spanni…...

OpenCV HighGUI 模块使用指南(Python 版)

用户让我编写一个 HighGUI 模块的使用指南,包括函数的使用和应用场景的实现。首先,我需要回顾 HighGUI 模块的主要功能:图像显示、视频捕获、鼠标和键盘事件。然后,按照用户提供的结构,整理每个部分的函数详解、代码示…...

SPI 机制与 Spring Boot AutoConfiguration 对比解析

一、架构效率革命性提升 1.1 类加载效率跃升 Spring Boot 2.7引入的AutoConfiguration.imports采用清单式配置加载,对比传统SPI机制: 传统SPI扫描路径:META-INF/services/** Spring Boot新方案:META-INF/spring/org.springfram…...

算法基础篇(1)(蓝桥杯常考点)

算法基础篇 前言 算法内容还有搜索,数据结构(进阶),动态规划和图论 数学那个的话大家也知道比较难,放在最后讲 这期包含的内容可以看目录 模拟那个算法的话就是题说什么写什么,就不再分入目录中了 注意事…...

【蓝桥杯速成】| 10.回溯切割

前面两篇内容我们都是在做有关回溯问题的组合应用 今天的题目主题是:回溯法在切割问题的应用 题目一:分割回文串 问题描述 131. 分割回文串 - 力扣(LeetCode) 给你一个字符串 s,请你将 s 分割成一些 子串&#xff…...

【Spring】深入理解 Spring 事务管理

文章目录 一、事务的基本概念​原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability) 二、Spring 事务管理的优势​简化事务管理代码提供多种事务管理方式整合…...

java学习笔记6

按住shift键,选择开始的一位和最后结束的一位来全选 面向对象特征之二:继承性(inheritance) 面向对象特征之二:继承性1.继承性的理解 > 生活上:财产的继承、颜值的继承 > 代码层面:> 自上而下:定义了一个类A,在定义另一个类B时&…...

人工智能在现代科技中的应用和未来发展趋势

人工智能(Artificial Intelligence,AI)是一种模拟人类智能思维和行为的技术,已经在现代科技中得到广泛应用。以下是人工智能在现代科技中的应用和未来发展趋势: 应用: 机器学习:机器学习是人工…...

第二十一章:模板与继承_《C++ Templates》notes

模板与继承 重点和难点编译与测试说明第一部分:多选题 (10题)第二部分:设计题 (5题)答案与详解多选题答案:设计题参考答案 测试说明 重点和难点 21.1 空基类优化(EBCO) 知识点 空基类优化(Empty Base Cla…...

STC89C52单片机学习——第35节: [16-1] AD/DA

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做! 本文写于:2025.03.23 51单片机学习——第35节: [16-1] AD/DA 前言开发板说明引用解答和科普一、AD问题…...

算法-最大公约数

1、约数: 1.1 试除法求约数 原理:只需要遍历最小的约数即可,较大的那个可以直接算出来。 import java.util.*; public class Main {static Scanner sc new Scanner(System.in);public static void main(String[] args) {int t sc.nextIn…...

在 SaaS 应用上构建 BI 能力的实战之路

SaaS 产品在持续运营过程中积累了大量数据,这些数据不仅是数字的记录,更是洞察市场趋势、优化产品功能、提升用户体验的宝贵资源。 因此,大部分的 SaaS 产品在发展到一定阶段后,都会开始构建自己的报表模块或分析模块,…...

代码随想录刷题day51|(二叉树篇)654.最大二叉树

一、二叉树基础知识 详见:代码随想录刷题day34|(二叉树篇)二叉树的递归遍历-CSDN博客 二、递归思路 递归三部曲 构造树一般采用前序遍历,因为先构造中间节点,然后递归构造左子树和右子树; 1.递归函数参数…...

深入理解 C++11 智能指针:独占、共享与弱引用的完美管理

文章目录 std::unique_ptr(独占式智能指针)std::shared_ptr(共享式智能指针)std::weak_ptr(弱引用智能指针)示例展示:智能指针的原理内存泄漏**什么是内存泄漏,内存泄漏的危害****如…...

1.2 编译器结构

编译器具有模块化的高层结构。还可以将模块化进一步细化。编译器可以看成多个阶段构成的流水线结构。 一种没有优化的编译器结构 更复杂的编译器结构...

文件操作助手

文件操作助手 在我们实现一个大型项目时,往往会有一个公共模块,这个公共模块是公用的,里面可能会包含文件操作助手、字符串操作助手、时间戳操作助手… 而我们今天就来实现一个文件操作助手,里面包含的功能有: 判断…...

线段树与扫描线 —— 详解算法思想及其C++实现

目录 一、线段树(Segment Tree) 基本概念 结构 操作 示例代码 二、扫描线(Sweep Line) 基本概念 应用场景 示例代码(矩形面积并集) 三、总结 一、线段树(Segment Tree) 基本…...

Leetcode 刷题笔记1 图论part04

leetcode 110 字符串接龙 def judge(s1, s2):count 0for i in range(len(s1)):if s1[i] ! s2[i]:count 1return count 1if __name__ __main__:n int(input())begin_str, end_str map(str, input().split())if begin_str end_str:print(0)exit()strlist []for _ in ran…...

快速入手:Nacos融合SpringCloud成为注册配置中心

快速入手:Nacos融合SpringCloud成为注册配置中心 前言安装Nacos项目搭建添加配置启动类添加注解运行项目服务调用RestTemplate 模式FeignClient 模式 前言 Spring Cloud是一系列框架的集合,提供了微服务架构下的各种解决方案,如服务治理、配…...

others-rustdesk远程

title: others-rustdesk远程 categories: Others tags: [others, 远程] date: 2025-03-19 10:19:34 comments: false mathjax: true toc: true others-rustdesk远程, 替代 todesk 的解决方案 前篇 官方 服务器 - https://rustdesk.com/docs/zh-cn/self-host/rustdesk-server-o…...

go:前后端分离

1.前端代码 新建一个前端文件夹,在该文件夹下新建一个.html文件,写入自己的html代码。 前端搞定。 2.后端代码 其核心是挂载路由接受前端传来的数据核心代码如下: func main() { // 服务运行提示 fmt.Println("go web server is runn…...

lodash 学习笔记/使用心得

lodash 学习笔记/使用心得 简单记一下 lodash 的一点学习笔记使用心得,最近也是打算清理一下所有的 dead code,然后发现我们用了好多的 lodash 方法。对比了之前的写法,重新看了一下官方文档,再自己重新动手写了点 util 之后发现…...

网络爬虫【爬虫库request】

我叫不三不四,很高兴见到大家,欢迎一起学习交流和进步 今天来讲一讲爬虫 Requests是Python的一个很实用的HTTP客户端库,完全满足如今网络爬虫的需求。与Urllib对比,Requests不仅具备Urllib的全部功能;在开发使用上&…...

AI日报 - 2025年3月24日

🌟 今日概览(60秒速览) ▎🤖 AGI突破 | Lyra生物序列建模架构效率惊人 在100生物任务中达最优,推理速度提升高达12万倍 ▎💼 商业动向 | OpenAI用户破4亿,Meta与Reliance探讨AI合作 生态扩展与全…...

Android平台毫秒级低延迟HTTP-FLV直播播放器技术探究与实现

一、前言 在移动互联网蓬勃发展的今天,视频播放功能已成为众多Android应用的核心特性之一。面对多样化的视频格式和传输协议,开发一款高效、稳定的视频播放器是许多开发者追求的目标。FLV(Flash Video)格式,尽管随着H…...

动态规划——混合背包问题

动态规划——混合背包问题 混合背包问题01背包与完全背包的混合:完全背包与多重背包的混合:三种背包混合混合背包OJ汇总 混合背包问题 将01背包、完全背包、多重背包混合起来的背包问题。也就是说,有的物品只可以取一次(01背包&a…...

数据库操作练习

一.向heros表中新增一列信息,添加一些约束,并尝试查询一些信息 //向表中添加一列age信息 alter table heros add column age int;//id列添加主键约束,设置自增 alter table heros modify column id int auto_increment primary key;//name列…...

3.milvus索引-HNSW

索引作用 加速大型数据集上的查询。 向量字段,仅只能创建一个索引。 milvus支持的向量索引类型大部分使用 近似最近邻搜索算法。ANNS该算法的核心不局限于返回最准确的结果,而是仅搜索目标的邻居。ANNS通过在可接受的范围内牺牲准确性提高检索效率。 …...

算法基础——栈

一、栈的概念 栈是⼀种只允许在⼀端进⾏数据插⼊和删除操作的线性表。 进⾏数据插⼊或删除的⼀端称为栈顶,另⼀端称为栈底。不含元素的栈称为空栈。进栈就是往栈中放⼊元素,出栈就是将元素弹出栈顶。 二、栈的模拟实现 1. 创建 本质还是线性表&#…...

开发语言漫谈-groovy

groovy是一门脚本语言,在前期的脚本语言中简单介绍了下。现在再深入介绍下,因为它是本平台上选用的脚本语言。所谓脚本语言就是不用编译,直接执行。这种特色非常适合做嵌入编程,即编即用。我们知道平台后台的业务开发语言是Java&a…...