数字时代的效率手册电子版

数字时代的效率手册电子版 本书是少数派上的关于效率的精选文章的合集,如果对生产力,效率有兴趣,可以观看本书. 我的github 本网站基于docsify构建,欢迎提出建议和意见. 开源地址: https://jimersylee.github.io/efficiency-handbook-in-the-digital-age/ 版权声明: 本书只作为学习交流,不保证其内容的准确性和完整性.内容仅供学习交流,请勿用于商业用途.本书基于购买的正版的<数字时代的效率手册>中的引用内容进行整理,方便个人查看和学习. 版权归原作者所有. 感谢原作者的辛勤付出.

July 29, 2022 · 1 min · 10 words · Jimmy

精进Notion-使用公式进行进度计算

精进Notion-使用公式进行进度计算 起因 在学习notion的过程中,经常发现一些好看的模板中,有好看的进度条,让人赏心悦目,于是,立即想学会如何实现. 原理 在阅读了官方的文档,和一些他人分享.的经验,知道了原来是使用notion的公式功能,notion官方提供了一些关键字,如下 properties: 对应某个database的列属性,这是被用来计算的变量 constants: 常量,如圆周率 functions:比如数学计算,字符串处理,日期计算,格式转换 有了这些关键字后,我想懂得程序的人应该知道能实现什么了,剩下的就是学习notion的语法糖了 实践 我准备实现一个书籍阅读进度条,想要计算进度条,最重要的几个变量是什么,书的总页数,这里新建一个叫Sum的property,还有已经读了的页数,用Readed这个property. 进度(Process),数学上形容就是 Process=Readed/Sum, 对应到notion的方程语法就是,其中round是取整数,prop就是取某个名字的属性的值. round(prop("Readed") / prop("Sum") * 100) 到这一步,其实进度就已经计算出来了,但是好看的进度条还没有,因此新建一个进度条列(Process Bar),公式为 slice("■■■■■■■■■■", 0, round(prop("Progress") * 0.1)) + slice("□□□□□□□□□□", 0, 10 - round(prop("Progress") * 0.1)) + " " + if(prop("Progress") < 10, "", if(prop("Progress") < 10, "0", "")) + if(prop("Progress") == 0, "0", format(prop("Progress"))) + "%" 其中slice关键字的意思是剪切,比如进度100%,则进度条全黑,10个方格都是黑的,完成的就是取(Process*0.1)个实心方格,未完成的进度用空心方格表示,+号把实心方格和空心方格连接在一起 ,最后在连接一个%符号,就能呈现处效果 小结 notion的formula功能可以实现进度条,指定日期提醒等功能,还是比较灵活的,虽然现在关键字不多,但是够用吧 这个玩玩可以,但是不要太钻研这些花里胡哨的东西,与使用notion的目的本末倒置了,形式是表面的,实质目的是为了进行知识管理与创造 参考 The Notion Formula Cheat Sheet

July 28, 2022 · 1 min · 68 words · Jimmy

如何提高工作效率

1、干完活别急着休息,要乘胜追击 2、找到你的“波峰时间” 3、适合的环境,让你更快进入工作状态 4、创造“心流体验”,让你深度工作 5、合理搭配工作,多任务并行

July 26, 2022 · 1 min · 5 words · Jimmy

冰豹鼠标换微动

型号 冰豹kone pure 问题 经过我高强度的使用(打游戏),鼠标左键单击变双击 维修准备 电络铁 夹具 松香 热风枪 吸锡器 各种型号的螺丝批 备用微动 欧姆龙D2FC-F-7N 维修过程 使用热风枪吹软鼠标底部的脚垫,然后使用刀片翘起一个角,然后撕开,这样可以看到底部总共有四个螺丝,全部拧开 拧开螺丝后打开上盖,可以看到整个结构,把看的见的小螺丝全部拧开 我们需要换的就是这个左键微动 电烙铁加热到450度,然后在焊接处放上少量松香,使用电烙铁加热融化锡,然后使用吸锡器吸走多余的锡,在保持融化状态下,使用尖嘴钳拔出原有的微动,接着插上新的微动,注意不要插反,然后焊上锡,大功告成 图黑色处为松香,无影响

July 26, 2022 · 1 min · 20 words · Jimmy

如何做好Team Leader

时常应该思考的事 核心竞争力是什么? 在公司的分工和定位是什么? 什么是短线的事?什么是长线的事? 大Leader应该做的5件事 选题 梯队 资源(预算+资源协调) 机制 辅导 技术负责人的能力要求是什么 让公司理解技术部门是成本中心,以及为什么是成本中心,让其他部门认可存在的价值,如何解释以下问题 迭代速度真的不能再快了? 工程化,技术重构类的价值阐述? 如何降本增效? 如何让高管和其他部门听懂研发部在干什么? 在高管会上,除了接锅和承诺修BUG,调整资源,还能聊什么话题? 可不可以在没有产品需求的情况下研发一个产品? 技术团队的产出如何量化? 技术部的话语权如何提升? 技术创新 应用爬虫获得更多数据,根据数据给用户打标 打通不同部门的数据壁垒 AI,以及自动化给可以节省哪些成本 reference 技术总监的烦恼

July 25, 2022 · 1 min · 26 words · Jimmy

机器学习实战-学习笔记之Decision Trees

项目地址:http://github.com/jimersylee/MachineLearningAction 决策树(Decision Trees) 类似20个问题的游戏 参与游戏的一方在脑海里想某个事物,其他参与者向他提问题,只允许提20个问题,问题的答案只能用对或错回答,问问题的人通过推断分解,逐步缩小带猜测事物的范围.决策树的工作原理与20个问题类似,用户输入一系列数据,然后给出游戏的答案 决策树 优点:计算复杂度不高,输入结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据 缺点:可能产生过度匹配问题 适用数据类型:数值型与标称型 决策树的一般流程 收集数据:可以适用任何方法 准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化 分析数据:可以适用任何方法,构造书完成之后,我们应该检查图形是否符合预期 训练算法:构造树的数据结构 测试算法:适用经验树计算错误率 适用算法:此步骤可以适用于任何监督学习算法,而适用决策树可以更好地理解数据的内在含义 # coding:utf-8from mathimport log import operator import matplotlib.pyplotas plt defcalcShannonEnt(dataSet): """ 计算给定数据集的香农熵,香农熵代表数据的无序程度,香农熵越大,数据集越无序 :param dataSet: 数据集 :return:香农熵的值 """ numEntries = len(dataSet)# 获得数据中实例的总数 labelCounts = {}# 声明一个字典# 为所有可能分类创建字典,它的键值是最后一列的数值for featVecin dataSet: currentLabel = featVec[-1]# 目前的标签=数据集的每行的最后一个元素if currentLabelnotin labelCounts.keys():# 如果键值不存在,则扩展字典并将当前键值加入字典 labelCounts[currentLabel] = 0# 初始化为0 labelCounts[currentLabel] = labelCounts[currentLabel] + 1# 每个键值都记录了当前类别出现的次数,出现一次加1 shannonEnt = 0.0 for keyin labelCounts: prob = float(labelCounts[key]) / numEntries# 使用所有类标签的发生频率计算类别出现的概率 shannonEnt = shannonEnt - prob * log(prob, 2)# 使用这个概率计算香农熵 以2为底求对数return shannonEnt defcreateDataSet(): """ 创建简单鱼类鉴定数据集 :return:dataSet(数据集),labels(标签) """ _dataSet = [ [1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no'] ] _labels = ['no surfacing', 'flippers'] return _dataSet, _labels myData, labels = createDataSet() print myData print calcShannonEnt(myData) """ result [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']] 0.970950594455 """ # 熵越高,则混合的数据也越多,我们可以在数据集中添加更多的分类,观察熵是如何变化的,这里我们增加第三个名为maybe的分类,测试熵的变化 myData[0][-1] = 'maybe'# 第0行的最后一个元素置为maybeprint myData print calcShannonEnt(myData) """ [[1, 1, 'maybe'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']] 1.37095059445 """ # 得到熵以后,我们就可以按照获取最大信息增益的方法划分数据集# 另一个度量集合无需程度的方法是`基尼不纯度`(Gini impurity),简单地说就是从一个数据集中随机选取子项,度量其被错误分类到其他分组里的概率""" 分类算法除了要测量信息熵,还需要划分数据集,度量花费数据集的熵,以便判断当前是否正确划分了数据集,我们将对每个特征划分数据集的结果计算一次信息熵,然后判断按照那个特征划分数据集是最好的划分方式 """ defsplitDataSet(dataSet, axis, value): """ 按照给定特征划分数据集 :param dataSet: 待划分的数据集 :param axis:划分数据集的特征位 :param value:预设特征值 :return: """ retDataSet = []# 创建新的list对象,因为函数中传递的是列表的引用,在函数内部对列表对象的修改,将会影响该列表对象的整个生存周期,因此需要创建一个新的列表for featVecin dataSet: if featVec[axis] == value:# 如果axis位的值等于预设的特征值 reducedFeatVec = featVec[:axis]# 取行数据的前axis位 reducedFeatVec.extend(featVec[axis + 1:])# 加上axis位后的元素 retDataSet.append(reducedFeatVec)# 就是将除了axis特征位的元素抽取出来return retDataSet # 测试splitDataSetprint "测试splitDataSet" myData, labels = createDataSet() print myData newData = splitDataSet(myData, 0, 1)# 将待测试数据的第0位为1的数据的其他特征和标签筛选出来print newData defchooseBestFeatureToSplit(dataSet): """ 选择最好的数据集划分方式 :param dataSet: 数据集 :return: """ numFeatures = len(dataSet[0]) - 1 # 计算整个数据的原始香农熵 baseEntropy = calcShannonEnt(dataSet) bestInfoGain = 0.0 bestFeature = -1 # 遍历数据集中的所有特征for iin range(numFeatures): # 创建唯一的分类标签列表 featList = [example[i]for examplein dataSet] uniqueVals = set(featList)# 将list转换为set,集合类型中每个值不同,从列表中创建集合是Python语言中得到列表中唯一元素值的最快方法 newEntropy = 0.0 # 计算每种划分方式的信息熵for valuein uniqueVals:# 遍历当前特征中的所以唯一属性值,对每个特征划分一次数据集 subDataSet = splitDataSet(dataSet, i, value) prob = len(subDataSet) / float(len(dataSet)) newEntropy += prob * calcShannonEnt(subDataSet)# 并对所有唯一特征值得到的熵求和 infoGian = baseEntropy - newEntropy# 信息增益=熵的减少值或者数据无序度的减少# 计算最好的信息增益if infoGian > bestInfoGain: bestInfoGain = infoGian bestFeature = i return bestFeature# 返回最好特征划分的索引值# 获取最好特征划分索引值print "获取最好特征划分索引值" myData, labels = createDataSet() print "dataSet:" + str(myData) print "best index:" + str(chooseBestFeatureToSplit(myData)) """ 代码表示,第0个特征是最好的用户划分数据集的特征 """ """ 递归构建决策树 """ defmajorityCnt(classList): """ 类似classify0部分的投票表决 创建键值为classList中唯一值的数据字典,字典对象存储了classList中每个类标签出现的频率,最后利用operator操作键值排序字典,返回出现次数最多的分类名称 :rtype: str :param classList: 分类名称的列表 :return: 返回出现次数最多的分类名称 """ classCount = {} for votein classList: if votenotin classCount.keys():# 如果投票的类别不在classCount字典的key中, classCount[vote] = 0# 则新建此key,value设置为0 classCount[vote] += 1 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] defcreateTree(dataSet, labels): """ 创建树,使用了递归 :param dataSet:数据集 :param labels: 分类标签 :return: 树结构 """ classList = [example[-1]for examplein dataSet]# 将数据集中的每一行的最后一个元素的值取出生成类别列表classListif classList.count(classList[0]) == len(classList):# 递归停止条件1return classList[0]# 类别完全相同时停止继续划分if len(dataSet[0]) == 1:# 递归停止条件2return majorityCnt(classList)# 遍历完所有特征时返回出现次数最多的 bestFeat = chooseBestFeatureToSplit(dataSet)# 选择最好的划分特征位 bestFeatLabel = labels[bestFeat]# 取出最好的标签 myTree = {bestFeatLabel: {}}# 初始化一个tree字典del (labels[bestFeat])# 删除最好的标签,防止树的下一个节点还使用此标签 featValues = [example[bestFeat]for examplein dataSet]# 创建最好的特征位的值所构建的list uniqueVals = set(featValues)# 生成唯一的特征位的值构成的集合setfor valuein uniqueVals: subLabels = labels[:]# 复制所有标签,且树不会和已经存在的标签搞混 myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels)# 递归创建树return myTree # 构建树测试print "构建树测试" myData, labels = createDataSet() myTree = createTree(myData, labels) print myTree # coding:utf-8import matplotlib.pyplotas plt# 导入绘制图库""" 绘制树图 """ decisionNode = dict(boxstyle="sawtooth", fc="0.8") leafNode = dict(boxstyle="round4", fc="0.8") arrow_args = dict(arrowstyle="<-") defgetNumLeafs(myTree): """ 获取叶节点的数目 :param myTree:树结构 :return: 叶节点的数目 """ numLeafs = 0 firstStr = myTree.keys()[0] secondDict = myTree[firstStr] for keyin secondDict.keys(): if type(secondDict[ key]).__name__ == 'dict':# test to see if the nodes are dictonaires, if not they are leaf nodes numLeafs += getNumLeafs(secondDict[key]) else: numLeafs += 1 return numLeafs defgetTreeDepth(myTree): """ 获取树的层数(深度) :param myTree: :return: 树的层数(深度) """ maxDepth = 0 firstStr = myTree.keys()[0] secondDict = myTree[firstStr] for keyin secondDict.keys(): if type(secondDict[ key]).__name__ == 'dict':# 判断此节点是否是字典,如果不是就是叶节点 thisDepth = 1 + getTreeDepth(secondDict[key])# 是字典,层数+1else: thisDepth = 1# 叶节点,层数为1if thisDepth > maxDepth: maxDepth = thisDepth return maxDepth defplotNode(nodeTxt, centerPt, parentPt, nodeType): """ 绘制节点 :param nodeTxt:节点名称 :param centerPt: 目前的位置 :param parentPt: 父节点的位置 :param nodeType: 节点类型 :return: """ createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction', xytext=centerPt, textcoords='axes fraction', va="center", ha="center", bbox=nodeType, arrowprops=arrow_args) defplotMidText(currentPt, parentPt, txtString): """ 绘制中间的文本 :param currentPt:目前的位置 :param parentPt: 父节点的位置 :param txtString: 想绘制的文本 :return: """ xMid = (parentPt[0] - currentPt[0]) / 2.0 + currentPt[0] yMid = (parentPt[1] - currentPt[1]) / 2.0 + currentPt[1] createPlot.ax1.text(xMid, yMid, txtString, va="center", ha="center", rotation=30) defplotTree(myTree, parentPt, nodeTxt):# if the first key tells you what feat was split on numLeafs = getNumLeafs(myTree)# this determines the x width of this tree depth = getTreeDepth(myTree) firstStr = myTree.keys()[0]# the text label for this node should be this cntrPt = (plotTree.xOff + (1.0 + float(numLeafs)) / 2.0 / plotTree.totalW, plotTree.yOff) plotMidText(cntrPt, parentPt, nodeTxt) plotNode(firstStr, cntrPt, parentPt, decisionNode) secondDict = myTree[firstStr] plotTree.yOff = plotTree.yOff - 1.0 / plotTree.totalD for keyin secondDict.keys(): if type(secondDict[ key]).__name__ == 'dict':# test to see if the nodes are dictonaires, if not they are leaf nodes plotTree(secondDict[key], cntrPt, str(key))# recursionelse:# it's a leaf node print the leaf node plotTree.xOff = plotTree.xOff + 1.0 / plotTree.totalW plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode) plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key)) plotTree.yOff = plotTree.yOff + 1.0 / plotTree.totalD # if you do get a dictionary you know it's a tree, and the first element will be another dictdefcreatePlot(inTree): fig = plt.figure(1, facecolor='white') fig.clf() axprops = dict(xticks=[], yticks=[]) createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)# no ticks# createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses plotTree.totalW = float(getNumLeafs(inTree)) plotTree.totalD = float(getTreeDepth(inTree)) plotTree.xOff = -0.5 / plotTree.totalW plotTree.yOff = 1.0 plotTree(inTree, (0.5, 1.0), '') plt.show() # def createPlot():# fig = plt.figure(1, facecolor='white')# fig.clf()# createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses# plotNode('a decision node', (0.5, 0.1), (0.1, 0.5), decisionNode)# plotNode('a leaf node', (0.8, 0.1), (0.3, 0.8), leafNode)# plt.show()defretrieveTree(i): listOfTrees = [{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}, {'no surfacing': {0: 'no', 1: {'flippers': {0: {'head': {0: 'no', 1: 'yes'}}, 1: 'no'}}}} ] return listOfTrees[i] # createPlot(thisTree) myTree = retrieveTree(0) createPlot(myTree)

July 21, 2022 · 5 min · 885 words · Jimmy

使用json_table实现json转关系表,进行聚合统计

表结构 article,"CREATE TABLE `article` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `content` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `create_at` bigint(20) DEFAULT NULL, `update_at` bigint(20) DEFAULT NULL, `user_id` bigint(20) DEFAULT NULL, `category_id` bigint(20) DEFAULT NULL, `tags_string` json DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" table data [ { "id": 1, "title": "标题1", "content": "content111", "create_at": 1640966400, "update_at": 123123123, "user_id": 12123132, "category_id": 2, "tags_string": "[\"linux\", \"dev\"]" }, { "id": 2, "title": "标题2", "content": "111", "create_at": 111, "update_at": 11, "user_id": 1, "category_id": 1, "tags_string": "[\"linux\"]" } ] SQL select a.tag,count(a.tag) as count from article, json_table(tags_string,'$[*]' columns (tag varchar(40) PATH '$')) a group by a.tag; Result linux,2 dev,1

July 15, 2022 · 1 min · 112 words · Jimmy

对女儿的语言暴力

事情的起因是早上女儿起床有起床气,在发脾气,要求妈妈陪,要求妈妈挑衣服,我去哄她也不行,指名道姓必须要妈妈,我也无可奈何. 在妈妈来回挑了好几趟衣服,女儿都不满意,还要换衣服,我生气了. 第一点:我觉得她现在都快5周岁了,应该能控制一下自己的情绪了,怎么还是经常有起床气,而且这个一发作就没人能哄,除了她妈妈,但是早上妈妈有很多要忙的,我觉得女儿不会体谅人. 第二点: 明明自己有审美观,知道自己喜欢什么样的衣服,但是不描述清楚,只让人猜,还挑三拣四好几次,这个行为习惯我觉得不好. 于是,我批评了女儿: 你没有长脚吗?喜欢什么衣服自己下床去衣柜里挑. 当时,没发生什么事情,老婆继续给女儿挑衣服,然后哄着起床吃早饭. 但是临出门上班的时候,老婆表达出情绪了: 有人这样说自己的女儿没有脚的吗? 看得出来很生气. 我反思了我自己的行为,我的出发点是好的,希望孩子自己的事情自己做,且能控制自己的情绪,但是语言欠妥. 就像丈母娘跟我说的一样,你是否能接受别人这样说你的女儿,换位思考一下即可. 于是,下班后,我郑重地跟女儿道歉,不应该说她没有脚,同时表达希望她不要乱发脾气,自己的事情还是尽量需要自己做,而且还跟儿子说清楚,不能笑别人的没有脚,因为他早上听到我这样说妹妹以后,他就学我说话,还觉得很搞笑. 孩子现在快5周岁了,正是快速模仿大人的行为的时候,所以作为家庭成员,不管是语言还是行为,都要特别注意,做到不说粗话,不表现暴力行为.

June 22, 2022 · 1 min · 15 words · Jimmy

go单元测试

go语言默认带测试工具,如果想递归测试目录下的所有测试代码,则可以执行以下代码 go test -mod=vendor -covermode=count -coverprofile=coverprofile.cov -run="^Test" -coverpkg=$(go list -mod=vendor ./... | grep -v "/test" | tr '\n' ',') ./... // 或 非 vendor 模式: go test -covermode=count -coverprofile=coverprofile.cov -run="^Test" -coverpkg=$(go list ./... | grep -v "/test" | tr '\n' ',') ./... 生成结果:coverprofile.cov 指令简单说明: mod=vendor: 加载依赖的方式:从本地vendor 目录加载。适用于服务器不能从外网下载依赖的情况 covermode: count: 统计代码访问次数;set: 统计代码是否被访问; atomic: 一般在并发工程中使用(?) run: 正则方式指定需要运行的测试方法 coverpkg: 指定业务代码路径,多个用逗号隔开,详细说明在后面 ./…:遍历当前目录下测试文件,包括子目录 关于为什么要使用coverpkg: 主要是因为我们的项目结构中,测试代码和业务代码是分开的,而不是放到同一个目录中。因此如果只指定测试方法,就无法识别到业务代码,来计算覆盖率了。 因此我们既需要指定测试代码路径(当然这里声明为 ./… 就可以了,只有_test 结尾的方法会自动作为测试方法),也需要指定业务代码路径(通过grep -v 和 tr 指令,最终将业务代码输出成 git/controller,git/database 的格式) 2、打开覆盖率报告 通过html 文件打开(推荐,能看到方法细节): go tool cover -html=coverprofile.cov 在命令行直接查看: go tool cover -func=coverprofile.cov

May 6, 2022 · 1 min · 82 words · Jimmy

GO Iris框架的全局异常处理

可以使用panic造成异常,而不是层层往上返回错误,在recover中处理错误 //启动设置 app := iris.New() app.Use(customRecover) //处理逻辑 func customRecover(ctx iris.Context) { defer func() { if err := recover(); err != nil { if ctx.IsStopped() { return } var stacktrace string for i := 1; ; i++ { _, f, l, got := runtime.Caller(i) if !got { break } stacktrace += fmt.Sprintf("%s:%d\n", f, l) } ctx.StatusCode(200) if ex, ok := err.(*commons.ErrorCode); ok { //如果是业务异常,则返回业务异常信息 _, _ = ctx.JSON(ex.Error()) ctx.Application().Logger().Printf("[%d] %s\n%s", ex.Code, ex.Message, stacktrace) } else { //如果不是认为抛出的异常,统一包装为系统异常 _, _ = ctx.JSON(commons.ErrorCodeSystem) errMsg := fmt.Sprintf("错误信息: %s", err) // when stack finishes logMessage := fmt.Sprintf("从错误中回复:('%s')\n", ctx.HandlerName()) logMessage += errMsg + "\n" logMessage += fmt.Sprintf("\n%s", stacktrace) // 打印错误⽇志 ctx.Application().Logger().Warn(logMessage) } // 返回错误信息 ctx.StopExecution() } }() ctx.Next() } //应用层使用 func (this *articleService) FindArticlesByYearMonth(queryParam *commons.QueryParams, yearMonth string) (list []models.Article, paging *commons.Paging) { //时间转时间戳 t, err := time.ParseInLocation("2006-01", yearMonth, time.Local) if err != nil { panic(commons.ErrorCodeParse) } } package commons import ( "encoding/json" ) var ( ErrorCodeSystem = NewError(1000, "系统异常") ErrorCodeNotLogin = NewError(1, "请先登录") ErrorCodeParse = NewError(2, "解析错误") ErrorCodeNotFound = NewError(3, "未找到") ErrorCodeRegisterFailed = NewError(4, "用户注册失败") ) func NewError(code int, text string) *ErrorCode { return &ErrorCode{code, text, nil, false, nil} } func NewErrorData(code int, text string, errorData interface{}) *ErrorCode { return &ErrorCode{code, text, nil, false, errorData} } func FromError(err error) *ErrorCode { if err == nil { return nil } return &ErrorCode{0, err.Error(), nil, false, nil} } type ErrorCode struct { Code int Message string Data interface{} Success bool ErrorData interface{} } func (e *ErrorCode) Error() string { marshal, _ := json.Marshal(e) return string(marshal) }

March 16, 2022 · 2 min · 248 words · Jimmy