项目中枚举的进阶用法(携带Java原理分析)

目录

  • 1 枚举的普通用法
    • 1.1 无参
    • 1.2 单个参数
    • 1.3 两个参数
  • 2 枚举的进阶用法(核心)
    • 2.1 优化
      • 2.1.1 需要改造的代码
      • 2.1.2 直接使用泛型
      • 2.1.3 使用反射---Class
      • 2.1.4 反射+泛型
    • 2.2 最终效果
    • 2.3 思考:类型擦除

遇到项目中这样一种写法,在枚举类的参数是一个.class对象,遂研究一二,发现别有洞天,其背后涉及到了泛型擦除、反射原理、运行时多态等,可以说这次研究,涉及到Java的方方面面,对Java的理解更上一层楼,希望读者可以耐心品味本文作者传达思想
在这里插入图片描述

1 枚举的普通用法

因为涉及到枚举,所以第一章节便给个示例,告诉读者为何要使用枚举?使用枚举的好处?使用枚举的细节?
希望通过此章节,以后遇到类似需求,能立马判断出能否使用枚举处理以及实现思路。

1.1 无参

需求:现在有两个规则(KEYWORDS_RULE,REGULAR_EXPRESSION_RULE)需要在一个枚举类中集中管理,方便管理以后拓展的规则,并且需要将规则信息发送给张三。

// 定义无参枚举
public enum ReferenceRelationSyncEnum {KEYWORDS_RULE,REGULAR_EXPRESSION_RULE;
}
// 单元测试
public static void main(String[] args) {// 第一种方式输出ReferenceRelationSyncEnum keywordsRule = ReferenceRelationSyncEnum.KEYWORDS_RULE;System.out.println(keywordsRule);// 第二种方式输出String s = ReferenceRelationSyncEnum.REGULAR_EXPRESSION_RULE.toString();System.out.println(s);}

输出效果
在这里插入图片描述

即使日后有100个规则,我们也仅需调用枚举类实现调用,获得这些规则的名称,并组装为一个List集合发送给张三,张三可能需要名称是REGULAR_EXPRESSION_RULE的规则,那他就会解析这个list

1.2 单个参数

需求:虽然我们可以发送这些规则的名称给张三,张三会解析这个List中的规则名称。一旦某一天我需要修改某个规则的名称,那张三为了适配我,也需要修改他的代码。这是我不希望看到的。
为了避免这个情况,我将每个规则指定一个type,例如KEYWORDS_RULE就是1,REGULAR_EXPRESSION_RULE就是2。如此一来,我传给张三的就是纯数字,即使我修改了规则名称,他也不需要变动他的代码。

public enum ReferenceRelationSyncEnum {KEYWORDS_RULE(1),REGULAR_EXPRESSION_RULE(2);private int type;public int getType() {return type;}ReferenceRelationSyncEnum(int type) {this.type = type;}
}
    public static void main(String[] args) {int type = ReferenceRelationSyncEnum.KEYWORDS_RULE.getType();System.out.println(type);int type2 = ReferenceRelationSyncEnum.REGULAR_EXPRESSION_RULE.getType();System.out.println(type2);}

在这里插入图片描述

优化前:张三按照规则名解析
优化后:信息更简洁了,张三按照type解析

1.3 两个参数

需求:正常的逻辑是:用户在界面勾选中文规则(关键字规则,正则规则),我们后端为了管理这种规则,创建枚举类,并给它们对应的英文名称(为了规范)。此外为了保障和张三之间消息的传递,我们又引入了type。

  public static void main(String[] args) {int type = ReferenceRelationSyncEnum.KEYWORDS_RULE.getType();System.out.println(type);int type2 = ReferenceRelationSyncEnum.REGULAR_EXPRESSION_RULE.getType();System.out.println(type2);System.out.println("------------------------------------");// 获取规则名称:通过枚举的实例方法调用String ruleName = ReferenceRelationSyncEnum.KEYWORDS_RULE.getRuleName();System.out.println(ruleName);// 获取规则名称:通过枚举类直接调用方法String ruleName2 = ReferenceRelationSyncEnum.getRuleName(2);System.out.println(ruleName2);}
public enum ReferenceRelationSyncEnum {KEYWORDS_RULE(1,"关键字规则"),REGULAR_EXPRESSION_RULE(2,"正则规则");private int type;private String ruleName;public int getType() {return type;}public String getRuleName() {return ruleName;}// java基本功:这里使用static有何益处-------可以被枚举类直接调用,不需要创建枚举实例public static String getRuleName(int type) {for (ReferenceRelationSyncEnum c : ReferenceRelationSyncEnum.values()) {if(c.getType() == type){return c.ruleName;}}return null;}ReferenceRelationSyncEnum(int type,String ruleName) {this.ruleName = ruleName;this.type = type;}
}
}

在这里插入图片描述

这样一来,不仅能保障之前的功能(和张三传递type),还能输出对应的中文规则
我们用这个中文规则能够干什么呢?
例前端传递给我们规则的中文名称 “正则规则” ,但我希望前端传递给我 “关键字规则” ,那么就需要加以判断
if( 前端的规则 == ReferenceRelationSyncEnum.getRuleName(1) )
是不是非常方便

2 枚举的进阶用法(核心)

需求:因为业务要求,我们会提供一个包含简单信息的Map,然后需要每个规则需要按照自己的特点重新组装得到新的NewMap。
例如我们为所有规则提供了Map,若是调用需要关键字规则,就包装得到NewMap1,发送给张三。若是需要正则规则,就包装为NewMap2,发送给张三。
在这里插入图片描述

先不考虑枚举,上述场景的最常见的解决思路就是定义一个抽象类,然后每个规则继承这个抽象类并重写这个抽象方法,如下图所示

在这里插入图片描述

// 抽象类
public abstract class AbstractRuleMsg {public abstract void buildRuleMag(Map<String, Object> map);
}
// 关键字规则继承
public class KeyWords extends AbstractRuleMsg {@Overridepublic void buildRuleMag(Map<String, Object> map) {System.out.println("这是NewMap1");// 重新包装得到NewMap1}
}
// 正则规则继承
public class RegularExperssion extends AbstractRuleMsg {@Overridepublic void buildRuleMag(Map<String, Object> map) {System.out.println("这是NewMap2");// 重新包装得到NewMap2}
}

重新梳理需求:
基于1.3章节实现的效果,指定一个type,我们就可以得到这个规则的中文名称,下一步我希望的效果是,指定一个type,我们就可以得到这个规则的类(KeyWords 或者RegularExperssion ),得到了这个类,我就可以调用这个类的方法:buildRuleMag(map )

那我们尝试按照之前的逻辑改造枚举类试试

public enum ReferenceRelationSyncEnum {KEYWORDS_RULE(1,"关键字规则",KeyWords),        // 改动点:第三个参数我们指定为对应的 类REGULAR_EXPRESSION_RULE(2,"正则规则",RegularExperssion);  // 改动点:第三个参数我们指定为对应的 类private int type;private String ruleName;private AbstractRuleMsg targetClass;              // 改动点:增加参数需要定义,既然都是继承的抽象方法,那就定义为抽象方法吧public int getType() {return type;}public String getRuleName() {return ruleName;}//  改动点:根据type获取对应的类public static AbstractRuleMsg getClass(int type) {for (ReferenceRelationSyncEnum c : ReferenceRelationSyncEnum.values()) {if(c.type == type){return c.targetClass;}}return null;}// 改动点:构造参数也需要适配ReferenceRelationSyncEnum(int type,String ruleName,AbstractRuleMsg targetClass) {this.ruleName = ruleName;this.type = type;this.targetClass= targetClass;}public static String getRuleName(int type) {for (ReferenceRelationSyncEnum c : ReferenceRelationSyncEnum.values()) {if(c.type == type){return c.ruleName;}}return null;}}

看起来很简单的样子,我们单元测试一下

public static void main(String[] args) {KeyWords targetClass = (KeyWords) ReferenceRelationSyncEnum.getClass(1);msg.buildRuleMag(new HashMap<>());RegularExperssion targetClass2 = (RegularExperssion) ReferenceRelationSyncEnum.getClass(2);msg2.buildRuleMag(new HashMap<>());}

一切看起来都很顺利的样子,是的没错,大致逻辑是没有问题的,只不过这里存在一处语法错误。
在枚举类的参数中,我们不应该直接传一个类本身,而是应该传一个类对象,这是枚举类的语法要求

KEYWORDS_RULE(1,"关键字规则",new KeyWords()),        // 改动点:第三个参数我们指定为对应的**类对象**REGULAR_EXPRESSION_RULE(2,,"正则规则",new RegularExperssion());  // 改动点:第三个参数我们指定为对应的**类对象**

看看效果
在这里插入图片描述

按照这样的方式,我们基本上就实现了,指定一个type,通过枚举类获得对应的类,调用该类的方法。如此一来,这个枚举类不仅仅管理了所有的规则名称,也管理了每个规则对应的类。简直是太方便维护了。(日后想知道该系统支撑哪些规则,或者改造某个规则类,通过枚举即可)

2.1 优化

上述代码功能上是没有任何问题了,但是在代码规范上不够优雅
需优化点A:在单元测试时,虽然我们指定了type,但是只能获得一个抽象类(注释的代码部分),为了得到该type对应的类,我们不得不进行一次类型转化,这就要求我们知道这个type对应的类是什么,这简直太麻烦了,接下里我们考虑如何避免这种情况
在这里插入图片描述
实际期待的效果:根据type自动的返回对应的类(大白话:我若指定type=1,返回类型自动是KeyWords;我若指定type=2,返回类型自动是RegularExperssion)
在这里插入图片描述

如何才能实现这个效果呢?什么效果----避免类型转化带来的麻烦
答案就是:使用泛型

为什么使用泛型就能避免类型转化代码的麻烦呢,如果你对泛型的知识还不够了解, 建议先阅读此文,点击查看

现在让我们开始尝试改造吧

2.1.1 需要改造的代码

调用getClass返回值类型是AbstractRuleMsg,需要将这一部分修改为泛型
在这里插入图片描述

2.1.2 直接使用泛型

tips:这一部分为小科普,正文从下面思路一开始
区分T和?的区别
观察如下代码: 在mian函数中,指定为?表示此时不确定类型,若确定类型就直接指定为String了。

public class Box<T> {private T item;public void setItem(T item) {this.item = item;}public T getItem() {return item;}
}public class Main {public static void main(String[] args) {Box<?> box = new Box<>();box.setItem("Hello");String item = box.getItem(); // 获取物品时只能使用Object类型接收System.out.println(item);System.out.println("-----------------------------");Box<String> box = new Box<>();box.setItem("Hello");String item = box.getItem(); // 获取物品时只能使用Object类型接收System.out.println(item);}
}

思路一 ↓


直接使用<T> 可以吗?

先回顾一下,使用<T> 会改变什么?

使用<T> ,可以直接指定类型

之前的代码:List list =Stringnew ArrayList();
使用<T>之后的代码: List<String> list = new ArrayList<>();

可以发现,使用<T>虽然解决了强制类型转化,但是仍需要指定类型,这并未满足我们的需求。因此使用<T>是不可以的


思路二 ↓


直接使用<> 可以吗?

tips中介绍了T和?区别,答案是:不可以

看来直接使用泛型是无法实现的

2.1.3 使用反射—Class

除了泛型,还有什么办法可以动态得到返回类型呢,答案就是反射!
如果你对反射还不了解, 可以阅读此文--------------------链接

接下来,就让我们尝试改造吧

类.class -------> 表示该类的类对象的引用,有了引用就有了一切
再啰嗦解释一次为何枚举的第三个参数必须为 KeyWords.class类型。注意看有参构造函数的参数targetClass类型是不是被定义为了Class,所以枚举的第三个参数必须与之对应,也是Class类型 Class a = KeyWords.class
在这里插入图片描述

public static void main(String[] args) throws Exception {// 获取类的.class,这个.class文件存这个类的元数据。就可以获取该类名称/该类的方法/创建该类实例....Class aClass = ReferenceRelationSyncEnum.getClass(1);Object o = aClass.newInstance();// 获取方法对象 buildRuleMag()Method method = aClass.getMethod("buildRuleMag",Map.class);Map <String,Object> map = new HashMap<>();method.invoke(o, map);}// 简化代码写法Object o = ReferenceRelationSyncEnum.getClass(2).newInstance();  // 为何这里返回的是Object,因为枚举中我们仅仅指定返回值是Class,若是Class<AbstractRuleMsg> ,这里返回值类型就是AbstractRuleMsg abstractRuleMsg = .....Method method = aClass.getMethod("buildRuleMag",Map.class);method.invoke(o, new HashMap<>());

在这里插入图片描述
确实,这样操作就可以在不知道type==1对应的返回类型KeyWords的情况下,仍调用该类的方法

Ps:这是之前的效果
在这里插入图片描述

看来使用反射确实能解决动态返回值类型的问题

2.1.4 反射+泛型

这是上述单元测试的代码

		// 简化代码写法Object o = ReferenceRelationSyncEnum.getClass(2).newInstance();  // 为何这里返回的是Object,因为枚举中我们仅仅指定返回值是ClassMethod method = aClass.getMethod("buildRuleMag",Map.class);method.invoke(o, new HashMap<>());

每次指定一个type,都需要使用反射,这样还是比较麻烦,要是能再简化一下就好了。
这是目前的单元测试代码
在这里插入图片描述

下图是我们期待的最终效果,解释一下这段代码:无论我们创建的是keyWords类的实例还是RegularExperssion类的实例,都用父类AbstractRuleMsg接收,调用子类重写父类的方法。(这是java多态的特点)

更详细的解释:


ReferenceRelationSyncEnum.getClass(1)时通过枚举类中的定义会得到KeyWords的类对象引用关系,newInstance()指使用KeyWords的类对象引用关系创建KeyWords类的实例。用父类AbstractRuleMsg接收,调用buildRuleMag()实际上调用的是KeyWords的重写方法,而不是AbstractRuleMsg的原始方法。


这就是java的运行时多态的特点,不知你可曾记得一个知识点:父类 A = new 子类,A只能调用父子共有的方法,不能调用子类特有的方法。jvm会在运行时动态决定调用谁的方法

在这里插入图片描述


如何才能实现这种操作,接下来请学习一种全新的思路

这是目前的代码
在这里插入图片描述

// 简化代码写法Object o = ReferenceRelationSyncEnum.getClass(2).newInstance();  // 为何这里返回的是Object,因为枚举中我们仅仅指定返回值是Class,若是Class<AbstractRuleMsg> ,这里返回值类型就是AbstractRuleMsg abstractRuleMsg = .....Method method = aClass.getMethod("buildRuleMag",Map.class);method.invoke(o, new HashMap<>());

因此我们需要定义返回值类型,改为什么合适呢?

若你想知道为什么仅定义为Class编译器就报错,可以看这里:
当编译器执行ReferenceRelationSyncEnum.getClass(2)时,发现枚举类定义的是Class,意思就是没有返回值类型限制(就是没有指定返回值类型),如下图。然后继续执行AbstractRuleMsg abstractRuleMsg2 = ReferenceRelationSyncEnum.getClass(2).newInstance();赋值时发现,将一个没有指定返回值类型 转化为 AbstractRuleMsg 类,会存在类型转化异常。

改为Class<AbstractRuleMsg>吧,
在这里插入图片描述
发现有参构造改动后,顶部代码提示类型不匹配。构造参数定义第三个参数为AbstractRuleMsg类型,顶部参数我们给的是KeyWords和RegularExperssion,自然不一致。那么该怎么办呢? 如下图

Class<? extends AbstractRuleMsg> (更规范,推荐)
这个通配符表示可以是 AbstractRuleMsg 或其任何子类,这种方式被称为通配符的上界(upper-bounded wildcard)。

Class<?> 也可以实现效果

具体区别阅读此文
在这里插入图片描述

2.2 最终效果

public enum ReferenceRelationSyncEnum {KEYWORDS_RULE(1,"关键字规则",KeyWords.class),REGULAR_EXPRESSION_RULE(2,"正则规则",RegularExperssion.class);private int type;private String ruleName;private Class<? extends AbstractRuleMsg> targetClass;public int getType() {return type;}public String getRuleName() {return ruleName;}public static Class<? extends AbstractRuleMsg> getClass(int type) {for (ReferenceRelationSyncEnum c : ReferenceRelationSyncEnum.values()) {if(c.getType() == type){return c.targetClass;}}return null;}ReferenceRelationSyncEnum(int type,String ruleName,Class<? extends AbstractRuleMsg> targetClass) {this.ruleName = ruleName;this.type = type;this.targetClass = targetClass;}public static String getRuleName(int type) {for (ReferenceRelationSyncEnum c : ReferenceRelationSyncEnum.values()) {if(c.getType() == type){return c.ruleName;}}return null;}}
    public static void main(String[] args) throws Exception {// 实际期待的结果AbstractRuleMsg abstractRuleMsg = ReferenceRelationSyncEnum.getClass(1).newInstance();abstractRuleMsg.buildRuleMag(new HashMap<>());AbstractRuleMsg abstractRuleMsg2 = ReferenceRelationSyncEnum.getClass(2).newInstance();abstractRuleMsg.buildRuleMag(new HashMap<>());}

在这里插入图片描述

2.3 思考:类型擦除

这种写法没问题
在这里插入图片描述
这种写法就会有问题
在这里插入图片描述

是什么原因导致的?为什么用AbstractRuleMsg类型接收就有问题,这是因为Class aClass = ReferenceRelationSyncEnum.getClass(1);这样写,原本保存KeyWords类的全部元数据(继承关系,类名等等),现在jvm类型擦除,丢失了继承关系,所以就是Object,而不能是AbstractRuleMsg了。

希望阅读完有所收获!

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

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

相关文章

NowCoder | KY11 二叉树遍历

NowCoder | KY11 二叉树遍历 OJ链接 简单来说就是构建这个二叉树定义结构体通过递归方式根据输入的字符串构建二叉树。对于输入字符串中的每个字符&#xff0c;如果是 ‘#’ 表示空节点&#xff0c;否则创建一个新节点&#xff0c;并递归地构建左右子树。 #include <limit…

24V转12V

24V转12V电源芯片是一种高效率、高稳定性的电源转换解决方案。它能够将输入电压范围为直流3.2V至36V的电能转换为输出电压范围为直流1.25V至35V的电能&#xff0c;且具有大92%的转换效率和3A的大输出电流。132*476I*OOO1 24V转12V电源芯片3A电流输出 可调输出 V*UIC9527 该电源…

微服务--一篇入门kubernets

Kubernetes 1. Kubernetes介绍1.1 应用部署方式演变1.2 kubernetes简介1.3 kubernetes组件1.4 kubernetes概念 2. kubernetes集群环境搭建2.1 前置知识点2.2 kubeadm 部署方式介绍2.3 安装要求2.4 最终目标2.5 准备环境2.6 系统初始化2.6.1 设置系统主机名以及 Host 文件的相互…

okhttp导致的内存溢出(OOM)sun.security.ssl.SSLSocketImpl

使用分析工具&#xff1a;MAT(Memory Analyzer Tool)、JvisualVM占用内存&#xff1a;sun.security.ssl.SSLSocketImpl 一、 项目场景&#xff1a; 功能&#xff1a;一个定时任务(xxl-job)采用线程池的方式多线程请求第三方拉取数据&#xff0c;网络框架使用okhttp3。 问题&am…

爬虫概念、基本使用及一个类型和六个方法(一)

目录 一、爬虫简介 1.什么是爬虫 2.爬虫的核心 3.爬虫的用途 4.爬虫的分类 5.反爬手段 二、Urllib基本使用 1.导入我们需要的包 2.定义一个url 3.模拟浏览器向服务器发送请求 4.获取响应中的页面的源码 5.打印数据 三、一个类型和六个方法 1.定义url&#xff0c;并…

代码级接口测试与单元测试的区别

关于接口测试 接口测试是一个比较宽泛的概念, 近几年在国内受到很多企业和测试从业者的追捧, 尤其是上层的UI在取悦用户的过程中迭代更新加快, UI自动化维护成本急剧上升的时代, 大家便转向了绕过前端的接口层面进行测试. 但是很多人, 对接口测试的理解并不完整, 事实上, 我们…

【数据结构】最短路径——Floyd算法

一.问题描述 给定带权有向图G&#xff08;V&#xff0c;E&#xff09;&#xff0c;对任意顶点 V &#xff08;ij)&#xff0c;求顶点到顶点的最短路径。 转化为&#xff1a; 多源点最短路径求解问题 解决方案一&#xff1a; 每次以一个顶点为源点调用Dijksra算法。时间复杂…

基于yolov8-道路裂缝检测

1 介绍 本文主要是搜集数据&#xff0c;从网上kaggle等网站找了2000多张图片&#xff0c;然后使用yolov8模型进行训练&#xff0c;最后只展示训练过程中的图片&#xff0c;如果有需要&#xff0c;可以联系&#xff1a;https://docs.qq.com/doc/DWEtRempVZ1NSZHdQ。

在线学习平台-需求分析(Java)

需求分析 研发集管理员、教务、教师、学生四种权限一体的中后台教务服务管理系统。其中管理员能够开设账号与角色分配&#xff0c;控制系统权限&#xff1b;教务能够进行班级管理、学员管理&#xff1b;教师能够进行课程与教学资源发布、作业发布与批改&#xff1b;学生能够观…

力扣刷题day1(两数相加,回文数,罗马数转整数)

题目1&#xff1a;1.两数之和 思路1和解析&#xff1a; //1.暴力枚举解法(历遍两次数组&#xff0c;时间复杂度O&#xff08;N^2)&#xff0c;空间复杂度O&#xff08;1&#xff09; int* twoSum(int* nums, int numsSize, int target, int* returnSize) {for (int i 0; i &…

【Selenium+Webmagic】基于JAVA语言实现爬取js渲染后的页面,附有代码

事先声明 笔者最近需要查看一些数据&#xff0c;自己挨个找太麻烦了&#xff0c;于是简单的学了一下爬虫。笔者在这里声明&#xff0c;爬的数据只为学术用&#xff0c;没有其他用途&#xff0c;希望来这篇文章学习的同学能抱有同样的目的。 枪本身不坏&#xff0c;坏的是使用枪…

如何制作教育培训小程序

教育培训行业近年来发展迅速&#xff0c;越来越多的机构开始意识到通过小程序来提供在线教育服务的重要性。小程序不仅可以为用户提供便捷的学习体验&#xff0c;还可以增加机构的知名度和品牌影响力。那么&#xff0c;如何制作一款教育培训小程序呢&#xff1f; 首先&#xff…

sqlmap400报错问题解决

python sqlmap.py -r sql.txt --batch --techniqueB --tamperspace2comment --risk 3 --force-ssl–batch 选项全部默认 不用再手动输入 –techniqueB 使用布尔盲注&#xff0c;该参数是指出要求使用的注入方式 –tamperspace2comment使用特殊脚本&#xff0c;space2comment是把…

【MySQL语言汇总[DQL,DDL,DCL,DML]以及使用python连接数据库进行其他操作】

MySQL语言汇总[DQL,DDL,DCL,DML] SQL分类1.DDL:操作数据库&#xff0c;表创建 删除 查询 修改对数据库的操作对表的操作复制表&#xff08;重点&#xff09;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 2.DML:增删改表中数据3.DQL&#xff1a;查询表中的记录…

jsp在线辅助教育系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 在线辅助教育系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

工厂生产数据展示基本布局Demo(提供素材)

效果图&#xff1a; <template><div class"app-container"><a-row :span"24"><a-col :span"12"><div class"divBox"><div class"flexBoxs"><div style"margin: 2px 5px;"…

在windows server系统下,快速部署自己的网站

目录 xampp简介xampp的作用xampp的安装方法Apache简介Apache的作用 本文主要介绍使用xampp软件包在windows server系统下&#xff0c;快速部署自己的网站。 xampp简介 XAMPP是一款基于Apache、MySQL、PHP和Perl的开源Web服务器软件包。XAMPP支持多个操作系统&#xff0c;包括W…

go写文件后出现大量NUL字符问题记录

目录 背景 看看修改前 修改后 原因 背景 写文件完成后发现&#xff1a; size明显也和正常的不相等。 看看修改前 buf : make([]byte, 64) buffer : bytes.NewBuffer(buf)// ...其它逻辑使得buffer有值// 打开即将要写入的文件&#xff0c;不存在则创建 f, err : os.Open…

MySQL数据备份

一、逻辑备份 备份的是建表、建库、插入等操作所执行SQL语句&#xff0c;适用于中小型数据库&#xff0c;效率相对较低。 本质&#xff1a;导出的是SQL语句文件 优点&#xff1a;不论是什么存储引擎&#xff0c;都可以用mysqldump备成SQL语句 缺点&#xff1a;速度较慢&…

Mysql分布式集群部署---MySQL集群Cluster将数据分成多个片段,每个片段存储在不同的服务器上

1.1 目的 部署MysqlCluster集群环境 1.2 MySQL集群Cluster原理 1 数据分片 MySQL集群Cluster将数据分成多个片段&#xff0c;每个片段存储在不同的服务器上。这样可以将数据负载分散到多个服务器上&#xff0c;提高系统的性能和可扩展性。 2. 数据同步 MySQL集群Cluster使…