万字解析设计模式之模板方法与解释器模式
一、模板方法模式
1.1概述
定义一个操作中算法的框架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
例如,去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业务、对银行工作人员进行评分等,其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样的,可以在父类中实现,但是办理具体业务却因人而异,它可能是存款、取款或者转账等,可以延迟到子类中实现。
1.2结构
模板方法(Template Method)模式包含以下主要角色:
抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成,可以是抽象方法和具体方法。
模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
基本方法:是实现算法各个步骤的方法,是模板方法的组成部分。基本方法又可以分为三种:
抽象方法(Abstract Method) :一个抽象方法由抽象类声明、由其具体子类实现。
具体方法(Concrete Method) :一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。
钩子方法(Hook Method) :在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。抽象类中的可选步骤,子类可以选择是否实现。
一般钩子方法是用于判断的逻辑方法,这类方法名一般为isXxx,返回值类型为boolean类型。
具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的组成步骤。
1.3实现
【例】炒菜
炒菜的步骤是固定的,分为倒油、热油、倒蔬菜、倒调料品、翻炒等步骤。现通过模板方法模式来用代码模拟。类图如下:
抽象类(Abstract Class)
package com.yanyu.Template;public abstract class AbstractClass {// 模板方法,定义了烹饪的步骤public final void cookProcess() {//第一步:倒油this.pourOil();//第二步:热油this.heatOil();//第三步:倒蔬菜this.pourVegetable();//第四步:倒调味料this.pourSauce();//第五步:翻炒this.fry();}public void pourOil() {System.out.println("倒油");}// 抽象方法,由子类实现,倒蔬菜的步骤public abstract void pourVegetable();// 抽象方法,由子类实现,倒调味料的步骤public abstract void pourSauce();// 具体方法,热油的步骤是一样的,直接实现public void heatOil() {System.out.println("热油");}// 具体方法,翻炒的步骤是一样的,直接实现public void fry(){System.out.println("炒啊炒啊炒到熟啊");}
}
具体子类(Concrete Class)
package com.yanyu.Template;public class ConcreteClass_BaoCai extends AbstractClass {@Overridepublic void pourVegetable() {System.out.println("下锅的蔬菜是包菜");}@Overridepublic void pourSauce() {System.out.println("下锅的酱料是辣椒");}
}
package com.yanyu.Template;public class ConcreteClass_CaiXin extends AbstractClass {@Overridepublic void pourVegetable() {System.out.println("下锅的蔬菜是菜心");}@Overridepublic void pourSauce() {System.out.println("下锅的酱料是蒜蓉");}
}
客户端类
package com.yanyu.Template;public class Client {public static void main(String[] args) {//炒手撕包菜ConcreteClass_BaoCai baoCai = new ConcreteClass_BaoCai();baoCai.cookProcess();//炒蒜蓉菜心ConcreteClass_CaiXin caiXin = new ConcreteClass_CaiXin();caiXin.cookProcess();}
}
注意:为防止恶意操作,一般模板方法都加上 final 关键词。
1.4优缺点
优点:
提高代码复用性
将相同部分的代码放在抽象的父类中,而将不同的代码放入不同的子类中。
实现了反向控制
通过一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制 ,并符合“开闭原则”。
缺点:
- 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
- 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
1.5应用场景
当你只希望客户端扩展某个特定算法步骤,而不是整个算法或其结构时,可使用模板方法模式;
模板方法将整个算法转换为一系列独立的步骤,以便子类能对其进行扩展,同时还可让超类中所定义的结构保持完整;
当多个类的算法除一些细微不同之外几乎完全一样时,你可使用该模式。但其后果就是, 只要算法发生变化,你就可能需要修改所有的类;
在将算法转换为模板方法时,你可将相似的实现步骤提取到超类中以去除重复代码。子类间各不同的代码可继续保留在子类中。
- 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。
1.6源码解析
InputStream类就使用了模板方法模式。在InputStream类中定义了多个 read() 方法,如下:
public abstract class InputStream implements Closeable {//抽象方法,要求子类必须重写public abstract int read() throws IOException;
public int read(byte b[]) throws IOException {return read(b, 0, b.length);}
public int read(byte b[], int off, int len) throws IOException {if (b == null) {throw new NullPointerException();} else if (off < 0 || len < 0 || len > b.length - off) {throw new IndexOutOfBoundsException();} else if (len == 0) {return 0;}
int c = read(); //调用了无参的read方法,该方法是每次读取一个字节数据if (c == -1) {return -1;}b[off] = (byte)c;
int i = 1;try {for (; i < len ; i++) {c = read();if (c == -1) {break;}b[off + i] = (byte)c;}} catch (IOException ee) {}return i;}
}
从上面代码可以看到,无参的
read()
方法是抽象方法,要求子类必须实现。而read(byte b[])
方法调用了read(byte b[], int off, int len)
方法,所以在此处重点看的方法是带三个参数的方法。在该方法中第18行、27行,可以看到调用了无参的抽象的
read()
方法。总结如下: 在InputStream父类中已经定义好了读取一个字节数组数据的方法是每次读取一个字节,并将其存储到数组的第一个索引位置,读取len个字节数据。具体如何读取一个字节数据呢?由子类实现。
二、解释器模式
2.1概述
解释器模式是一种行为型设计模式,它定义了一个语言的语法,并用一个解释器来解释该语言中的句子。通常,解释器模式用于将一个复杂的语言拆分成一些简单的语言元素,使它们易于理解和操作。
2.2结构 
- 抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。定义了一个抽象的解释操作,所有具体的表达式都需要实现这个接口。
- 终结符表达式(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。它实现了抽象表达式的解释方法。
- 非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。它们通过递归的方式来解释语言。
- 环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。环境保存了要解释的语言,它提供了一个接口给表达式来获取和设置环境的状态。
2.3实现
【例】设计实现加减法的软件
抽象表达式
package com.yanyu.Expressioner;//抽象角色AbstractExpression
public abstract class AbstractExpression {//定义了一个解释器方法,接收一个上下文对象,返回解释结果public abstract int interpret(Context context);
}
终结符表达式(Terminal Expression)角色
package com.yanyu.Expressioner;// 终结符表达式角色 变量表达式
// 变量表达式是解释器模式中的一种角色,用于表示语言中的变量。在这里,Variable类表示一个变量,它继承自抽象表达式角色AbstractExpression。
public class Variable extends AbstractExpression {private String name;// 构造函数,用于初始化变量名public Variable(String name) {this.name = name;}// interpret方法用于解释上下文中的表达式,这里是返回变量对应的值@Overridepublic int interpret(Context ctx) {return ctx.getValue(this);}// 重写toString方法,返回变量名的字符串表示@Overridepublic String toString() {return name;}
}
package com.yanyu.Expressioner;// 终结符表达式角色
// 终结符表达式是解释器模式中的一种角色,用于表示语言中的基本元素。在这里,Value类表示一个具体的值,它继承自抽象表达式角色AbstractExpression。
public class Value extends AbstractExpression {private int value;// 构造函数,用于初始化值public Value(int value) {this.value = value;}// interpret方法用于解释上下文中的表达式,这里是返回值本身@Overridepublic int interpret(Context context) {return value;}// 重写toString方法,返回值的字符串表示@Overridepublic String toString() {return Integer.valueOf(value).toString();}
}
非终结符表达式(Nonterminal Expression)角色
package com.yanyu.Expressioner;// 非终结符表达式角色 加法表达式
// 加法表达式是解释器模式中的一种非终结符表达式角色,用于表示语言中的加法操作。在这里,Plus类表示加法表达式,它继承自抽象表达式角色AbstractExpression。public class Plus extends AbstractExpression {private AbstractExpression left; // 左操作数private AbstractExpression right; // 右操作数// 构造函数,用于初始化左右操作数public Plus(AbstractExpression left, AbstractExpression right) {this.left = left;this.right = right;}// interpret方法用于解释上下文中的表达式,这里是返回左右操作数的解释结果相加的值@Overridepublic int interpret(Context context) {return left.interpret(context) + right.interpret(context);}// 重写toString方法,返回加法表达式的字符串表示,形式为 (左操作数 + 右操作数)@Overridepublic String toString() {return "(" + left.toString() + " + " + right.toString() + ")";}
}
package com.yanyu.Expressioner;///非终结符表达式角色 减法表达式
public class Minus extends AbstractExpression {private AbstractExpression left;private AbstractExpression right;public Minus(AbstractExpression left, AbstractExpression right) {this.left = left;this.right = right;}@Overridepublic int interpret(Context context) {return left.interpret(context) - right.interpret(context);}@Overridepublic String toString() {return "(" + left.toString() + " - " + right.toString() + ")";}
}
环境(Context)角色
package com.yanyu.Expressioner;import java.util.HashMap;
import java.util.Map;// 环境类
// 环境类用于存储变量和它们的值,在解释器模式中起到承上启下的作用,为解释器提供解释所需的上下文信息。
public class Context {private Map<Variable, Integer> map = new HashMap<Variable, Integer>();// 将变量和对应的值存入map中public void assign(Variable var, Integer value) {map.put(var, value);}// 获取变量对应的值public int getValue(Variable var) {Integer value = map.get(var);return value;}
}
客户端类
package com.yanyu.Expressioner;// 测试类
// 客户端类Client用于测试解释器模式的功能。在这里,我们创建了一个上下文对象context,以及五个变量a、b、c、d、e,并为这些变量赋值。
// 然后,我们构造了一个复杂的表达式,包括加法和减法操作,并通过interpret方法解释这个表达式,输出其计算结果。public class Client {public static void main(String[] args) {Context context = new Context(); // 创建上下文对象Variable a = new Variable("a"); // 创建变量aVariable b = new Variable("b"); // 创建变量bVariable c = new Variable("c"); // 创建变量cVariable d = new Variable("d"); // 创建变量dVariable e = new Variable("e"); // 创建变量econtext.assign(a, 1); // 为变量a赋值context.assign(b, 2); // 为变量b赋值context.assign(c, 3); // 为变量c赋值context.assign(d, 4); // 为变量d赋值context.assign(e, 5); // 为变量e赋值// 构造复杂的表达式,包括加法和减法操作AbstractExpression expression = new Minus(new Plus(new Plus(new Plus(a, b), c), d), e);// 解释并输出表达式的计算结果System.out.println(expression + "= " + expression.interpret(context));}
}
2.4 优缺点
1,优点:
易于改变和扩展文法。
由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
实现文法较为容易。
在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂。
增加新的解释表达式较为方便。
如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合 "开闭原则"。
2,缺点:
对于复杂文法难以维护。
在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护。
执行效率较低。
由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦
2.5应用场景
- 当语言的文法较为简单,且执行效率不是关键问题时。
- 当问题重复出现,且可以用一种简单的语言来进行表达时。
- 当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候。
三、模板方法模式实验
任务描述
高校网上办事系统中的需要对场地预约、设备维修、教职工请假、车辆登记等申请单进行审核,因此需要与众多子系统进行对接。子系统会将用户填写好的申请单推送到网上办事系统中,处理完后将单号返回给子系统。对接的申请单种类有多个,每种申请单的处理流程是一样的(数据校验-申请单解析-申请单入库-提交审核-自动备份),最大的区别在于不同的申请单,解析方法不同。
本关任务:以场地预约申请单(
VenueApplication
)和教职工请假申请单(LeaveApplication
)为例,模拟实现申请单处理流程。实现方式
分析目标算法, 确定能否将其分解为多个步骤。 从所有子类的角度出发, 考虑哪些步骤能够通用, 哪些步骤各不相同;
创建抽象基类并声明一个模板方法和代表算法步骤的一系列抽象方法。 在模板方法中根据算法结构依次调用相应步骤。 可用
final
最终修饰模板方法以防止子类对其进行重写;虽然可将所有步骤全都设为抽象类型, 但默认实现可能会给部分步骤带来好处, 因为子类无需实现那些方法;
可考虑在算法的关键步骤之间添加钩子;
为每个算法变体新建一个具体子类, 它必须实现所有的抽象步骤, 也可以重写部分可选步骤。
编程要求
根据提示,补充右侧编辑器文件
Client.java
中 Begin-End 内的代码,完成实验。其它文件的代码不需要修改。测试说明
平台会对你编写的代码进行测试:
测试输入:
张三
LeaveApplication
预期输出:张三数据校验
教职工请假申请单数据解析
张三申请单入库
张三提交审核
张三自动存档
测试输入:
报告厅
VenueApplication
预期输出:报告厅数据校验
场地预约申请单数据解析
报告厅申请单入库
报告厅提交审核
报告厅自动存档
抽象类
public abstract class ApplicationTemplate {public boolean execute(String data){this.checker(data);this.dataAnalysis(data);this.proposalSave(data);this.submit(data);this.autoSave(data);return true;}/*** 数据校验*/public void checker(String data){System.out.println(data+"数据校验");}/*** 数据解析*/public abstract void dataAnalysis(String data);/*** 数据入库*/public void proposalSave(String data){System.out.println(data+"申请单入库");}/*** 提交审核*/public void submit(String data){System.out.println(data+"提交审核");}/*** 自动存档*/public void autoSave(String data){System.out.println(data+"自动存档");}}
具体类
public class LeaveApplication extends ApplicationTemplate{@Overridepublic void dataAnalysis(String data) {System.out.println("教职工请假申请单数据解析");}
}
public class VenueApplication extends ApplicationTemplate{@Overridepublic void dataAnalysis(String data) {System.out.println("场地预约申请单数据解析");}
}
客户端类
import java.util.Scanner;public class Client {public static void main(String[] args) {/********** Begin *********/Scanner scanner = new Scanner(System.in);String applicant = scanner.nextLine();String applicationType = scanner.nextLine();if (applicationType.equals("LeaveApplication")) {LeaveApplication leaveApplication = new LeaveApplication();leaveApplication.execute(applicant);} else if (applicationType.equals("VenueApplication")) {VenueApplication venueApplication = new VenueApplication();venueApplication.execute(applicant);} else {System.out.println("Invalid application type");}/********** End *********/}
}
相关文章:

万字解析设计模式之模板方法与解释器模式
一、模板方法模式 1.1概述 定义一个操作中算法的框架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 例如,去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业…...

apipost接口200状态码,浏览器控制台500状态码
后端 url 登录login方法 login(){this.$refs.loginForm.validate(async valid > {if (!valid) return// 由于data属性是一个json对象,需要进行解构赋值{data:result},进行状态码判断const {data: result} await this.$http.post(/api/doLogin,this.…...

Instant Web API .Net Core Crack
Instant Web API .Net Core 是立即构建即时数据库 Web API,无需编码。在几分钟内生成您的 Web API,以更快地构建应用程序。使用 VS 2022 和 Entity Framework Core 为任何 MS SQL 数据库生成 Web API。 新功能 - 使用 Visual Studio 2022 为 PostgreSQL …...

vue项目使用easyplayer播放m3u8直播推流
官网 青犀视频 代码库 / 示例 / demo EasyPlayer 示例效果: 项目背景如图 后端给了m3u8的直播地址 协议是 hls / flv 市面上很多第三方热门播放库都可以完成该多屏播放方式 如Video.js 问题在于 分多屏时 会存在性能问题 并且关闭播放器后 即便删除Dom或调用停…...

Python报错:AttributeError(类属性、实例属性)
Python报错:AttributeError(类属性、实例属性) Python报错:AttributeError 这个错误就是说python找不到对应的对象的属性,百度后才发现竟然是初始化类的时候函数名写错了 __init__应该有2条下划线,如果只有…...

vue+springboot读取git的markdown文件并展示
前言 最近,在研究一个如何将我们git项目的MARKDOWN文档获取到,并且可以展示到界面通过检索查到,于是经过几天的摸索,成功的研究了出来 本次前端vue使用的是Markdown-it Markdown-it 是一个用于解析和渲染 Markdown 标记语言的 …...

多功能PHP图床源码:Lsky Pro开源版v2.1 – 最新兰空图床
Lsky Pro是一款功能丰富的在线图片上传和管理工具,即兰空图床。它不仅可以作为个人云相册,还可以用作写作贴图库。 该程序的初始版本于2017年10月由ThinkPHP 5开发,经过多个版本的迭代,于2022年3月发布了全新的2.0版本。 Lsky Pro…...

Hive内置表生成函数
Hive内置UDTF 1、UDF、UDAF、UDTF简介2、Hive内置UDTF 1、UDF、UDAF、UDTF简介 在Hive中,所有的运算符和用户定义函数,包括用户定义的和内置的,统称为UDF(User-Defined Functions)。如下图所示: UDF官方文档…...

电源控制系统架构(PCSA)之电源控制框架概览
目录 6 电源控制框架 6.1 电源控制框架概述 6.1.1 电源控制框架低功耗接口 6.1.2 电源控制框架基础设施组件 6 电源控制框架 电源控制框架是标准基础设施组件、接口和相关方法的集合,可用于构建SoC电源管理所需的基础设施。 本章介绍框架的主要组件和低功耗接…...

Sentinel 监控数据持久化(mysql)
Sentinel 实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制,即自行扩展实现 MetricsRepository 接口(修改 控制台源码)。 本文通过使用Mysql持久化监控数据。 1.构建存储表(…...

基于法医调查算法优化概率神经网络PNN的分类预测 - 附代码
基于法医调查算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于法医调查算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于法医调查优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要:针对PNN神…...

canvas高级动画001:文字瀑布流
canvas实例应用100 专栏提供canvas的基础知识,高级动画,相关应用扩展等信息。 canvas作为html的一部分,是图像图标地图可视化的一个重要的基础,学好了canvas,在其他的一些应用上将会起到非常重要的帮助。 文章目录 示例…...

抽象类, 接口, Object类 ---java
目录 一. 抽象类 1.1 抽象类概念 1.2 抽象类语法 1.3 抽象类特性 1.4 抽象类的作用 二. 接口 2.1 接口的概念 2.2 语法规则 2.3 接口的使用 2.4 接口间的继承 2.5 抽象类和接口的区别 三. Object类 3.1 toString() 方法 3.2 对象比较equals()方法 3.3 hash…...

SOAP 协议和 HTTP 协议:深入解读与对比
SOAP 和 HTTP 协议 SOAP 协议 SOAP( Simple Object Access Protocol)是一种用于在节点之间交换结构化数据的网络协议。它使用XML格式来传输消息。它在 HTML 和 SMTP 等应用层协议的基础上进行标记和传输。SOAP 允许进程在整个平台、语言和操作系统中进…...
Unity发布IOS后,使用xcode打包报错:MapFileParser.sh:Permissiondenied
1.错误提示 使用xcode打包错误提示:/Users/mymac/Desktop/myproject/MapFileParser.sh: Permission denied 2.解决方案 打开控制台输入:chmod ax /Users/mymac/Desktop/myproject/MapFileParser.sh。按回车键执行,然后重新使用xcode发布程序…...

2021年12月 Scratch(三级)真题解析#中国电子学会#全国青少年软件编程等级考试
Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 执行下列程序,屏幕上可以看到几只小猫? A:1 B:3 C:4 D:0 答案:B 第2题 下列程序哪个可以实现:按下空格键,播放完音乐后说“你好!”2秒? A: B: C:...

mac上Homebrew的安装与使用
打开终端:command空格 ,搜索‘’终端 ’,打开终端 在终端中输入以下命令并按下回车键: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"这个命令会自动下载并安装…...

YOLOv5 分类模型 预处理 OpenCV实现
YOLOv5 分类模型 预处理 OpenCV实现 flyfish YOLOv5 分类模型 预处理 PIL 实现 YOLOv5 分类模型 OpenCV和PIL两者实现预处理的差异 YOLOv5 分类模型 数据集加载 1 样本处理 YOLOv5 分类模型 数据集加载 2 切片处理 YOLOv5 分类模型 数据集加载 3 自定义类别 YOLOv5 分类模型…...

在arm 64 环境下使用halcon算法
背景: halcon,机器视觉领域神一样得存在,在windows上,应用得特别多, 但是arm环境下使用得很少。那如何在arm下使用halcon呢。按照官方说明,arm下只提供了运行时环境,并且需要使用价值一万多人民…...

H5(uniapp)中使用echarts
1,安装echarts npm install echarts 2,具体页面 <template><view class"container notice-list"><view><view class"aa" id"main" style"width: 500px; height: 400px;"></view></v…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...