兼容pc端和移动端的滑块校验

news/2024/9/18 9:43:58/ 标签: 前端, javascript, vue.js
组件
javascript"><template><canvas :class="cvsClass" :width="props.width" :height="props.height" ref="cvs"></canvas>
</template><script setup>
import { ref, reactive, watch, nextTick } from "vue";
const props = defineProps({// 是否开启服务端验证servertest: {type: Boolean,default: false},width: {type: Number,default: 220},height: {type: Number,default: 45},strokeWidth: {type: Number,default: 3},// 滑块宽度dropWidth: {type: Number,default: 50},// 已激活验证背景色 activeBgColor | 验证中激活的背景色 testIngBgColor| 验证成功激活的背景色 successBgColor// 验证成功文本色 tipSucColor| 验证失败文本色 tipTailColor | 验证中的文本色 tipTestIngColor | 待验证文本色 tipNoneColor// 移动滑块背景色 dropColor// 滑块原始背景色  slideColor// 滑块颜色dropColor: {type: String,default: "#fff"},// 待验证文本色tipNoneColor: {type: String,default: "#000"},// 验证成功文本色tipSucColor: {type: String,default: "#fff"},// 验证中的文本色tipTestIngColor: {type: String,default: "#fff"},// 验证失败文本色tipTailColor: {type: String,default: "#ee0a24"},// 验证中提示testTip: {type: String,default: "正在验证..."},// 滑块背景色颜色slideColor: {type: String,default: "#fff"},// 滑块背景色颜色tipTxt: {type: String,default: "拖动滑块验证"},// 验证通过背景色successBgColor: {type: String,default: "#07c160"},//  验证失败背景色tailBgColor: {type: String,default: "#ee0a24"},// 已激活的背景色activeBgColor: {type: String,default: "#888"},// 验证中激活的背景色testIngBgColor: {type: String,default: "#ff976a"},// 验证成功文字提示successTip: {type: String,default: "恭喜你验证通过!"},// 验证失败文字提示failTip: {type: String,default: "验证失败,请重试"},// 文本大小fontSize: {type: Number,default: 14}
});
const emit = defineEmits(["statu"]);
let vfcx = null;
const cvs = ref();
const cvsClass = ref("cur-none");
let vfcres = {startX: 0, //开始拖动滑块位置endX: 0, //结束拖动滑块位置timed: 0, //拖动所用时间 || 低于30毫秒认定为机器guiji: [], //拖动轨迹 | 连续2个2数之差相同判定为机器width: props.width
};
const vfcStatu = reactive({statu: "none"
});
// 监听数据,并发给父级
watch(vfcStatu, res => {emit("statu", res, vfcres);// 验证成功if (res.statu === "success") {vfcx.anmateOff = false;vfcx.activeBgColor = props.successBgColor;vfcx.tipTxt = props.successTip;vfcx.colors.slideColor = props.successBgColor;vfcx.evNone();} else if (res.statu === "tail") {vfcx.reset();vfcx.tipTxt = props.failTip;vfcx.fontColor = props.tipTailColor;vfcx.draw();}
});
/*** 验证器* @param {Element} cvsEl canvas元素* @param {String, default:'cur-none'} cvsClass canvas的class* @param {Boolear, default:fasle} vfcres 验证结果* @param {Number, default:5} strokeWidth 滑块内边距* @param {Number,default:50} dropWidth 滑块宽度* @param {color,default:'#fff'} dropColor 移动滑块背景色* @param {color,default:'#e8e8e8'} slideColor 滑块背景色颜色* @param {color,default:'skyblue'} activeBgColor 已激活验证背景色* @param {color,default:'#ff976a'} testIngBgColor 验证中激活的背景色* @param {color,default:'#07c160'} successBgColor 验证成功激活的背景色* @param {color,default:'#07c160'} tipSucColor 验证成功文本色* @param {color,default:'#ee0a24'} tipTailColor 验证失败文本色* @param {color,default:'#fff'} tipTestIngColor 验证中的文本色* @param {color,default:'#000'} tipNoneColor 待验证文本色* @param {String,default:'向右滑动验证'} tipTxt 文字提示* @param {String,default:'太棒了,恭喜你验证通过!'} successTip 验证成功文字提示* @param {String,default:'验证失败,请重试...'} failTip 验证失败文字提示* @param {Bool} servertest 是否开启前端验证模式* @param {String} testTip 验证提示*/
class Vfcs {constructor(cvsEl, cvsClass, vfcres, vfcStatu, strokeWidth, dropWidth, fontSize, servertest, colors, tipTxt) {this.cvsEl = cvsEl;this.vfcres = vfcres;this.cvsClass = cvsClass;this.strokeWidth = strokeWidth;this.dropWidth = dropWidth;this.vfcStatu = vfcStatu;this.colors = colors;this.fontSize = fontSize;this.dwonIsPath = false; //是否按下验证滑块this.ctx = null;this.allTipTxts = tipTxt;this.tipTxt = this.allTipTxts.tipTxt;this.fontColor = this.colors.tipNoneColor;this.activeBgColor = this.colors.activeBgColor;this.servertest = servertest;this.guiji = [];this.startTime = 0;this.endTime = 0;this.startX = 0;this.startY = 0;this.moveX = 0;this.moveY = 0;this.fontOp = 1; //文本透明度this.met = false;this.offX = 0; //x轴的位移this.minX = this.strokeWidth / 2;this.maxX = this.cvsEl.width - this.dropWidth - this.strokeWidth;// this.dropX最大值 -》  cW - this.dropWidth - this.strokeWidth / 2// this.dropX最小 -》   this.strokeWidth / 2this.dropX = this.minX + this.offX; // 滑块位置this.toTouchEnd = false;//是否按下滑块this.isDown = false;this.testAm = null; //验证中动画的idthis.anmateOff = true; //动画开关this.evsName = []; //事件名this.evsFun = [this.down.bind(this), this.move.bind(this), this.up.bind(this)]; //事件方法this.init();}init() {this.ctx = this.cvsEl.getContext("2d");this.draw();this.evsName = this.evType();// 给canvas添加事件this.evsName.forEach((evName, i) => (i === 0 ? this.cvsEl.addEventListener(evName, this.evsFun[i]) : document.addEventListener(evName, this.evsFun[i])));}// 绘制draw() {let cW = this.cvsEl.width,cH = this.cvsEl.height,c = this.ctx;c.clearRect(0, 0, cW, cH);c.globalAlpha = this.fontOp; // 设置图像透明度c.fillRect(0, 0, cW, cH);c.fillStyle = this.colors.slideColor;c.strokeStyle = this.colors.slideColor;c.lineWidth = this.strokeWidth;c.fillRect(0, 0, cW, cH);c.strokeRect(0, 0, cW, cH);// 激活背景色c.fillStyle = this.activeBgColor;c.strokeStyle = this.activeBgColor;c.fillRect(this.minX + 2, this.minX, this.offX, cH - this.strokeWidth);// 文本提示c.textAlign = "center";c.textBaseline = "middle";c.fillStyle = this.fontColor;c.font = `${this.fontSize}px 黑体`;c.fillText(this.tipTxt, cW / 2, cH / 2);// 验证失败// 待验证 | 验证中if (this.vfcStatu.statu === "none" || this.vfcStatu.statu === "testing" || this.vfcStatu.statu === "servertest" || this.vfcStatu.statu === "tail") {// 滑块c.beginPath();c.fillStyle = this.colors.dropColor;c.rect(this.dropX, this.minX, this.dropWidth, cH - this.strokeWidth);c.fill();// 箭头c.lineWidth = 2;// 右边箭头c.moveTo(this.dropX + this.dropWidth / 1.7 - 5, this.strokeWidth + 10);c.lineTo(this.dropX + this.dropWidth / 1.7 + 5, cH / 2);c.lineTo(this.dropX + this.dropWidth / 1.7 - 5, cH - this.strokeWidth - 10);// 左边箭头c.moveTo(this.dropX + this.dropWidth / 1.7 - 15, this.strokeWidth + 10);c.lineTo(this.dropX + this.dropWidth / 1.7 - 5, cH / 2);c.lineTo(this.dropX + this.dropWidth / 1.7 - 15, cH - this.strokeWidth - 10);c.stroke();c.closePath();// 验证成功} else if (this.vfcStatu.statu === "success") {// 滑块c.beginPath();c.fillStyle = this.colors.dropColor;c.rect(this.dropX, this.minX, this.dropWidth, cH - this.strokeWidth);c.fill();c.closePath();// 圈c.beginPath();c.fillStyle = this.colors.successBgColor;c.arc(this.dropWidth / 2 + this.dropX, cH / 2, cH / 3, 0, 2 * Math.PI);c.fill();c.closePath();// 勾c.beginPath();c.lineWidth = 3;c.lineJoin = "bevel";c.lineCap = "round";c.strokeStyle = this.colors.dropColor;c.moveTo(this.dropX + this.dropWidth / 2 - 8, cH / 2 + 1);c.lineTo(this.dropX + this.dropWidth / 2.1, cH / 1.6);c.lineTo(this.dropX + this.dropWidth / 2 + 8, cH / 2 - 5);c.stroke();c.closePath();}}// 滑块按下down(ev) {if (this.vfcStatu.statu === "testing" || this.vfcStatu.statu === "servertest") return;this.setXY(ev);//按下滑块this.isDown = true;this.startTime = new Date().getTime();// 若按下滑块const isPath = this.ctx.isPointInPath(this.startX, this.startY);this.dwonIsPath = isPath;}// 滑块移动move(ev) {if (this.vfcStatu.statu === "testing" || this.vfcStatu.statu === "servertest") return;this.setXY(ev);const isPath = this.ctx.isPointInPath(this.moveX, this.moveX);// pc 鼠标变手势if (ev.x) isPath === true ? (this.cvsClass.value = "pointer") : (this.cvsClass.value = "cur-none");const x = Number(this.moveX.toFixed(2));const y = Number(this.moveY.toFixed(2));const moveTime = new Date().getTime();this.guiji.push({ x, y, moveTime });if (this.dwonIsPath === false || this.moveX <= 0) return;if (this.isDown === true) {// 若滑到尾部this.toTouchEnd = this.touchDrosToEnd();if (this.toTouchEnd === true) this.up();this.draw();}}// 滑块抬起up() {if (this.vfcStatu.statu === "testing" || this.vfcStatu.statu === "servertest" || this.offX === 0 || this.dwonIsPath === false || this.moveX <= 0) return;this.endTime = new Date().getTime();this.vfcres.startX = this.startX; //鼠标/手指按下位置this.vfcres.endX = this.dropX + this.dropWidth + this.minX; //鼠标/手指抬起位置this.vfcres.timed = this.endTime - this.startTime; //耗时this.vfcres.guiji = this.guiji; //滑动轨迹this.vfcres.width = this.cvsEl.width;this.dwonIsPath = false;this.isDown = false;// 未滑动到尾部if (this.toTouchEnd === false) {this.dropX = this.minX; // 滑块位置this.offX = 0;this.tipTxt = this.allTipTxts.failTip;this.fontColor = this.colors.tipTailColor;// 滑动到尾部} else {this.vfcStatu.statu = "testing";this.testAdmate(); //开启动画// 验证中this.fontColor = this.colors.tipTestIngColor;this.tipTxt = this.allTipTxts.testTip;this.activeBgColor = this.colors.testIngBgColor;this.dropX = this.maxX + this.minX; // 滑块位置const test = this.testVer();setTimeout(() => {// 前端验证通过if (test === "success") {// 已开启前端验证模式if (this.servertest === true) {this.vfcStatu.statu = "servertest";} else {this.vfcStatu.statu = "success";}// 前端验证不通过} else {this.vfcStatu.statu = "tail";}}, 1000);}this.draw();this.guiji = [];}// 重置滑块reset() {this.dropX = this.minX; // 滑块位置this.anmateOff = false;this.activeBgColor = this.colors.activeBgColor;this.fontColor = this.colors.tipNoneColor;this.tipTxt = this.allTipTxts.tipTxt;this.offX = 0;this.toTouchEnd = false;this.guiji = [];this.draw();}// 解绑事件evNone() {this.evsName.forEach((evName, i) => (i === 0 ? this.cvsEl.removeEventListener(evName, this.evsFun[i]) : document.removeEventListener(evName, this.evsFun[i])));}// 验证中动画testAdmate() {// 文本透明度if (this.met === false && this.fontOp >= 1) {this.met = true;} else if (this.met === true && this.fontOp <= 0.5) {this.met = false;}this.met === false ? (this.fontOp += 0.015) : (this.fontOp -= 0.015);this.draw();cancelAnimationFrame(this.testAm);this.testAm = window.requestAnimationFrame(this.testAdmate.bind(this));if (this.anmateOff === false) {cancelAnimationFrame(this.testAm);this.fontOp = 1;this.testAm = null;this.met = false;this.anmateOff = true;}this.draw();}/*** 验证是否滑动到尾部* @return {Number}  return true 到尾部,false 没到尾部*/touchDrosToEnd() {const x = this.offX + this.dropWidth + this.strokeWidth;const isSuccess = x >= this.cvsEl.width;return isSuccess;}// 设置xy坐标setXY(ev) {if (ev.type === "touchstart") {this.startX = ev.touches[0].clientX - this.cvsEl.getBoundingClientRect().left;this.startY = ev.touches[0].clientY - this.cvsEl.getBoundingClientRect().top;}if (ev.type === "touchmove") {this.moveX = ev.touches[0].clientX - this.cvsEl.getBoundingClientRect().left;this.moveY = ev.touches[0].clientY - this.cvsEl.getBoundingClientRect().top;}// ///pc事件 //if (ev.type === "mousedown") {this.startX = ev.x - this.cvsEl.getBoundingClientRect().left;this.startY = ev.y - this.cvsEl.getBoundingClientRect().top;}if (ev.type === "mousemove") {this.moveX = ev.x - this.cvsEl.getBoundingClientRect().left;this.moveY = ev.y - this.cvsEl.getBoundingClientRect().top;}// 防止滑块溢出指定范围if (ev.type === "mousemove" || ev.type === "touchmove") {this.offX = this.moveX - this.startX;if (this.offX > this.maxX) this.offX = this.maxX;if (this.offX < this.minX) this.offX = this.minX;this.dropX = this.minX + this.offX; // 滑块位置}}// 事件类型evType() {const isMobile = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i) !== null;const events = isMobile ? ["touchstart", "touchmove", "touchend"] : ["mousedown", "mousemove", "mouseup"];return events;}/*** 滑动轨迹信息 | 计算滑动轨迹每2数之间的差值 | 出现次数等* @return {Object(chaArr,repeatX,repeatY,repeatMaxXCount,repeatMaxYCount,allCount)} chaArr → 每2数之间的插值 | repeatX → x轴每2数之间的差值与重复数  | repeatY → y轴每2数之间的差值与重复数 |  repeatMaxXCount → x轴每重复数最多的次数 | repeatMaxYCount → y轴每重复数最多的次数*/arrCmp() {// 重复的数量const repeatX = [];const repeatY = [];const timed = [];const chaArr = this.guiji.reduce((prev, itm, i, arr) => {if (i === arr.length - 1) return prev;const nv = arr[i + 1];const chaX = Number((nv.x - itm.x).toFixed(2));const chaY = Number((nv.y - itm.y).toFixed(2));const timeCha = nv.moveTime - itm.moveTime;timed.push(timeCha); //时间差// 是否有重复的数组const repeatXIndex = repeatX.findIndex(item => item.num === chaX);const repeatYIndex = repeatY.findIndex(item => item.num === chaY);// xy轴每2数差数据if (repeatXIndex === -1) {const obj = {num: chaX,count: 1};repeatX.push(obj);} else {repeatX[repeatXIndex].count++;}if (repeatYIndex === -1) {const obj = {num: chaY,count: 1};repeatY.push(obj);} else {repeatY[repeatYIndex].count++;}prev.push({ x: chaX, y: chaY });return prev;}, []);// 所有重复次数const findXCount = [];const findYCount = [];repeatX.forEach(it => findXCount.push(it.count));repeatY.forEach(it => findYCount.push(it.count));const repeatMaxXCount = Math.max(...findXCount); //x重复最多的次数const repeatMaxYCount = Math.max(...findYCount); //y重复最多的次数const repeatMaxTimed = Math.max(...timed); //滑动时间重复最多的次数return {chaArr,repeatX,repeatY,repeatMaxXCount,repeatMaxYCount,repeatMaxTimed};}// 前端验证//  x轴最大波动大于数等于所有波动长度则为人机 | y轴最大波动数等于所有波动长度则为人机 | 滑动时间低于50毫秒不通过  | 时间波动最大次数大于滑动轨迹长度的3/1为人机testVer() {// return 'tail'// 滑动所用时间低于50毫秒 是人机if (this.vfcres.timed < 50) return "tail";const sliderInfo = this.arrCmp(); //处理滑动轨迹信息// 时间波动最大次数等于sliderInfo.chaArr.length滑动轨迹长度为人机const timeTest = sliderInfo.repeatMaxTimed === sliderInfo.chaArr.length;if (timeTest === true) return "tail";// x轴最大波动大于数等于所有波动长度则为人机if (sliderInfo.repeatMaxXCount === sliderInfo.repeatX) return "tail";//  y轴最大波动数等于所有波动长度则为人机if (sliderInfo.repeatMaxYCount === sliderInfo.chaArr.length) return "tail";// 是真人return "success";}
}
nextTick(() => {const colors = {activeBgColor: props.activeBgColor,testIngBgColor: props.testIngBgColor,successBgColor: props.successBgColor,tipSucColor: props.tipSucColor,tipTailColor: props.tipTailColor,tipTestIngColor: props.tipTestIngColor,tipNoneColor: props.tipNoneColor,dropColor: props.dropColor,slideColor: props.slideColor};const tipTxt = {testTip: props.testTip,tipTxt: props.tipTxt,successTip: props.successTip,failTip: props.failTip};vfcx = new Vfcs(cvs.value, cvsClass, vfcres, vfcStatu, props.strokeWidth, props.dropWidth, props.fontSize, props.servertest, colors, tipTxt);
});
</script>
页面调用
javascript"><slider-vfc @statu="slideVerify" />
// 滑块验证
const slideVerify = vfcStatu => {props.form.verify = vfcStatu.statu == "success";
};

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


http://www.ppmy.cn/news/1525069.html

相关文章

【C++开发中XML 文件的妙用】

在C中&#xff0c;XML&#xff08;可扩展标记语言&#xff09;文件通常用于存储配置数据、应用程序设置、数据交换格式等。由于其结构化和可读性强的特点&#xff0c;XML文件在配置管理、序列化、跨平台数据交换以及软件国际化等方面有着广泛的应用。 XML 文件的妙用 配置管理…

Go语言结构体和元组全面解析

Go语言中的复合类型与其应用 在编程中&#xff0c;标准类型虽然方便&#xff0c;但无法满足所有需求。Go通过支持结构体和元组类型&#xff0c;为开发者提供了自定义数据类型的能力。本文将介绍如何定义结构体、如何使用指针操作结构体、如何通过元组返回多个值等内容&#xf…

技术速递|VS Code Java 8月更新 - 重要 Gradle 更新!用户体验与入门向导增强

作者&#xff1a;Nick Zhu 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎来到 Visual Studio Code for Java 八月更新&#xff01;在这篇博客中&#xff0c;我们将涵盖重要 Gradle 更新、更多用户体验改进以及更好的入门体验&#xff0c;马上开始吧&#xff01; Gradle 更…

【开源免费】基于SpringBoot+Vue.JS图书个性化推荐系统(JAVA毕业设计)

本文项目编号 T 015 &#xff0c;文末自助获取源码 \color{red}{T015&#xff0c;文末自助获取源码} T015&#xff0c;文末自助获取源码 目录 一、系统介绍1.1 业务分析1.2 用例设计1.3 时序设计 二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究…

Rust 函数

文章目录 发现宝藏1. 函数的基本定义2. 函数调用3. 函数参数4. 语句与表达式5. 返回值总结 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【宝藏入口】。 函数是 Rust 编程中的核心组成部分&…

【Go】Golang连接数据库使用HTTP协议

离开你是傻是对是错 是看破是软弱 这结果是爱是恨或者是什么 如果是种解脱 怎么会还有眷恋在我心窝 那么爱你为什么 &#x1f3b5; 黄品源/莫文蔚《那么爱你为什么》 package mainimport ("context""fmt""log""time&q…

从100G到400G:利用多模光纤升级数据中心网络

数据中心网络的持续发展 数据中心网络的持续发展涵盖了两个关键方面。首先&#xff0c;必须应对由机器学习和物联网等数据密集型应用所带来的带宽和流量需求的增长挑战&#xff0c;这些应用正在推动现有10G和40G链路的升级&#xff1b;其次&#xff0c;为了满足日益提升的可持…

Leetcode 三数之和

解题思路&#xff1a; 排序数组&#xff1a;首先对数组进行排序&#xff0c;以便使用双指针技术来查找三元组。双指针法&#xff1a;在遍历数组时&#xff0c;遍历固定三元组的第一个元素&#xff0c;然后使用双指针&#xff08;分别指向剩下数组的头和尾并相向而行&#xff0…

基于图谱的记忆存储 - mem0 graph memory + neo4j

log 日志版 【LLM最强大脑】基于图谱的记忆存储 - mem0 graph memory neo4j_哔哩哔哩_bilibili 获取API Key 谷歌邮箱注册&#xff0c;需科学上网&#xff0c;你知道的┗|&#xff40;O′|┛ 嗷~~ 获取 mem0ai key Dashboard | Mem0.ai 获取 neo4j key Neo4j Graph Databa…

WebLogic 笔记汇总

WebLogic 笔记汇总 一、weblogic安装 1、创建用户和用户组 groupadd weblogicuseradd -g weblogic weblogic # 添加用户,并用-g参数来制定 web用户组passwd weblogic # passwd命令修改密码# 在文件末尾增加以下内容 cat >>/etc/security/limits.conf<<EOF web…

SpringMVC基于注解使用

01-拦截器介绍 首先在pom.xml里面加入springmvc的依赖 创建拦截类 在spring-mvc.xml配置拦截器配置 创建控制类测试 拦截器中处理方法之前的方法介绍 拦截器中处理方法之后&#xff0c;渲染之前的方法介绍 拦截器中处理方法之后&#xff0c;渲染之后的方法介绍 判断拦截器和过…

element form rules 验证数组对象属性时如何写判断规则

需求&#xff1a;一个el-form-item里放了2个下拉选择框&#xff0c;规定是最少选择一个&#xff0c;最多这俩都选择值&#xff1b;下拉框的值设置为对象了&#xff0c;所以这俩select的值组成了一个数组里的两个对象 逻辑&#xff1a;感觉只需要把第一个下拉框值&#xff08;即…

默认端口被占用后,如何修改Apache2 端口

你可以通过以下步骤修改 Apache2 的默认端口&#xff08;80 端口&#xff09;&#xff1a; 1. 修改 Apache2 配置文件 首先&#xff0c;你需要编辑 Apache2 的端口配置文件&#xff1a; sudo nano /etc/apache2/ports.conf在文件中&#xff0c;你会看到类似以下的内容&#…

【PostgreSQL里的restartpoint重启点】

不知道大家有没有关注过&#xff0c;配置文件里archive_cleanup_command参数的注释部分有着这么一句"command to execute at every restartpoint",意思是在每个restartpoint时执行的命令。 提起checkpoint大家可能比较熟悉&#xff0c;对于这个restartpoint&#xff…

fs::copy中的recursive和overwriting的区别是什么,如何一起使用

fs::copy中的recursive和overwriting参数关注于文件复制的不同方面&#xff1a; recursive&#xff1a;当设置为true时&#xff0c;允许复制目录及其所有子目录和文件。如果设置为false&#xff0c;则只复制单个文件或空目录。 overwriting&#xff1a;当设置为true时&#xf…

vulnhub靶机:21 LTR: Scene1

下载 下载地址&#xff1a;https://www.vulnhub.com/entry/21ltr-scene-1,3/ 导入靶机 一直按默认的来&#xff0c;一直下一步 修改网卡 修改靶机和 kali 攻击机网络模式为仅主机模式 把仅主机模式的 IP 修改为 192.168.2.0 信息收集 主机发现 arp-scan -l 靶机 IP 是 192.…

golang panic

在 Go 语言中&#xff0c;panic 是一种用于处理异常情况的机制。当程序遇到无法继续执行的错误时&#xff0c;可以使用 panic 来引发运行时错误。以下是关于 panic 的一些关键点和示例。 1. 使用 panic 当调用 panic 时&#xff0c;程序会停止执行当前函数&#xff0c;并开始…

传承中华文脉·弘扬北疆文化“四季内蒙古演出季”区内外文艺院团交流演出活动即将启动

为推进“北疆文化”品牌建设&#xff0c;由内蒙古自治区文化和旅游厅、呼和浩特市人民政府主办&#xff0c;呼和浩特市文化旅游广电局承办的传承中华文脉弘扬北疆文化——“四季内蒙古演出季”区内外文艺院团交流演出活动将于9月14日至11月期间在呼和浩特市举办。 传承中华文脉…

Go入门指南(The Way to Go) 完整版PDF

The Way To Go可以说是入门 Go 的经典书籍&#xff0c;这本书有内容丰富各种资料链接&#xff0c;这是截止到目前&#xff0c;大叔看到的写得最好的go 语言教材&#xff0c;非常详细.一口气读下来&#xff0c;舍不得放手&#xff0c;大叔强烈推荐你去学习 百度网盘分享

环境变量和本地变量

什么是环境变量&#xff1f; 环境变量是操作系统里保存的具有特殊用途的参数 常见的环境变量 PATH&#xff1a;存放操作系统默认的搜索路径 HOME&#xff1a;当前的登入账户 USER&#xff1a;当前的使用者 如何查询环境变量&#xff1f; echo $name&#xff08;环境变量名…