技术

  • go logo
    Go,  技术,  编程语言

    golang 指针参数传递与赋值

    golang指针参数传递,实际也是值拷贝,传递的是指针所指向的内存地址。 所以,在函数内部的修改,实际是对该内存地址的修改,所以会生效。 但若在函数内部,给该指针参数重新分配一块新的内存地址,然后再对其修改,那么修改 对于函数外部而言就不会再生效了。 传递nil, 函数内初始化 函数内重新初始化 不重新赋值,只修改 综上所述,开发过程中一定要牢记 ,对于指针参数的重新赋值一定要慎重。

  • 技术
    技术

    高效开发流程

    作为程序员,日常的工作大部分都是在进行开发工作,一个优秀的开发流程,能够很好的提高开发的效率以及质量。 第一步:问题定义 每一个开发任务,必然都是为了解决某个问题的。所以,在进行开发工作前,首先要明确的就是为什么要进行开发。 问题的定义,一般都来自于目标用户,毕竟所有的软件系统面向的群体就是用户。 举例来说: 我想要看我自己以前发布的评论 这个人发布的内容我很喜欢,我想以后他发布内容我能够第一时间看到 路边叫车太麻烦了,要是能够通过手机直接叫车就好了 这个excel表格太乱了,排个序就好了 这些就是问题定义,从用户的角度出发,用户实际遇到的需要解决的问题。 那么明确问题定义,这对程序员来说有什么用呢? 首先,你能够知道进行开发工作要解决的实际问题是什么。 其次,有些问题实际上根部就不需要开发,就像第四个示例,excel自身一个简单的排序就可以了,耗费时间编程实现,成本和收益无疑是不成正比的。 第二步:需求定义 在开发之前,必须要有一个正式的需求文档,明确具体要实现的功能。 一般而言,需求文档是产品根据第一步从用户角度出发的问题定义,进行整理归纳成,从产品角度出发的需求定义。 而对于程序员来讲,有的程序员,拿到需求文档后就会开始进行开发工作(方案设计,编码等等),不会关心需求文档是否合理,也不会关心该需求来自用户提出的什么问题(问题定义),更不会关心需求文档是否符合问题定义,是否是解决问题的最佳方案。 而这些,恰恰是一名优秀的程序员所必需要考虑的事情,有句话说的好,“没有产品思维的程序员不是好程序员”,而对于一些不合理的需求进行驳回,或者跟产品进一步讨论确定新的需求方案,都是一个优秀的程序员所必备的技能。 程序员最大的自我否定就是把自己当成工具人!要从整个产品甚至整个公司的角度宏观的体现自身的价值。 第三步:技术方案设计 明确具体的需求后,接下来就可以进行实际的技术方案设计了。 根据项目需求的大小,此处的方案设计可能包含从宏观的架构设计到具体的每个类,每个接口的功能实现。 这一步是真正开始开发前非常有必要做的准备,可以从整体上把握开发中可能遇到的问题以及开发需要的工作量,实际上,在完成这一步后,给出的排期才是最为合理的。 第四步:编码 此时就可以按照设计的技术方案,进行编码了。 当然,编码中需要考虑的设计模式,代码规范,命名等等,我们这里就不做详细描述了,总之,尽量写优质,易读的代码。 第五步:单元测试 虽然写单元测试,会耗费不少的时间,但与其之后让测试人员不停的找你,你再不断的排查代码,解决bug,这耗费的时间和心力完全是可以接受的。 而且,测试人员测试,有时候并不能完全覆盖你的代码逻辑,但单元测试却能够很大程度上覆盖大部分的逻辑,能够避免出现一些意料之外bug。 还有一点就是,如果以后代码上有什么变更,变更完直接跑一遍已经写好的单元测试,是非常的方便而且舒心的,至少可以知道变更并不会对原先的逻辑造成什么影响。 第六步:提交测试 自测完,实际上就已经可以提交测试了。 提交测试的前提是,你自己已经能够确保代码不会有什么bug,测试人员测试的目的,是为了做上线前的最后核验,找到那些漏网之鱼的bug,而绝不应该是一大批的显而易见的bug。…

  • 技术
    技术

    代码的艺术-命名

    在编写代码过程中,无论是变量,类还是函数等等,一个清晰可以理解的名字,是至关重要的,能够让别人更加清晰的了解你的思路以及代码的含义。 可以说,每一个命名,都是一个简短的注释。 一、选择具有清晰表达含义的命名 日常编码中,我们经常用到get, size等进行命名,但实际上其并没有准确的表达出需要表达的信息,别人能够从中获取到的信息很少。 比如说get,get到了什么,从哪里get, 缓存还是数据库,或者从接口获取等等,这些信息都没有清晰的表达出来。举例来说,如果我们用这样的名字,如getUserNameFromCache,是不是更加的清晰了呢? 下面同样举了一些常见的命名词汇,准确的运用这些词汇,能够让你在命名时,更好的表达自己的代码逻辑和作用。 代码的艺术-常用词汇 二、避免使用空洞的名字 何为空洞的名字?这里指的就是tmp, retval, foo这类名字。 以tmp举例来说,如果变量的唯一目的就是临时存储,如: 这时用tmp就很好,因为它的作用就仅仅只是临时存储,且生命周期只是几行代码之间。 但如果不是这种场景,仅仅只是因为懒惰就是用类似tmp之类的名字,就有些不合时宜了。 即便有些场景,确实是临时存储的含义,但最好也要更加明确些信息,如: tmpFile, tmpCache等等,不要只是单纯的tmp了事。 同时,常用的另外一种情况就是循环迭代的时候,我们常用的都是i, j, k,或者 k, v, key, val, 如果可以的话,换成具体表达含义的词汇会更好,如: 三、命名中尽可能附带更多的信息 如果关于一个变量,有什么更重要的事情必须让读者知道,那么将额外的词加入到命名中就是一个非常好的做法。 如我们最常见的场景,数据库中有很多的数据表,很多的表里面都有一个字增ID字段,如果我们将这个字段都命名为 id , 那么在代码中,就会出现大量的 id…

  • 技术
    技术

    代码的艺术-常用词汇

    以下是整理的一些我们在编码过程中,经常会用到的一些词汇,希望能够让你在命名变量、类、函数等时,能够使用更加合适的命名。 成对反义词 add 添加 remove 移除 input 输入 output 输出 insert 插入 delete 删除 create 创建 destory 销毁 get 获取 release 释放 show 显示 hide 隐藏 start 开始 stop 停止 open 打开 close…

  • Rocketmq,  技术,  服务组件

    Rocketmq知识点整理(一)

    自研NameServer 摒弃业界常用的Zookeeper,使用自研的NameServer实现元数据的管理(Topic路由信息等)。 从实际场景出发,topic路由在集群中无需保持强一致性,仅需保持最终一致性,且能够容忍分钟级别的不一致,因此,rockermq自研的NameServer摒弃了集群之间的相互通信,而是相互独立,不仅极大的降低了NameServer实现的复杂度,降低了对网络的要求,同时也因此,性能相比Zookeeper有了极大地提升。 高效的IO存储机制 为了追求消息发送的高吞吐量,rocketmq引入了内存映射机制。rocketmq以文件组的方式,存储消息的存储文件,每个文件组内的单个文件大小固定,所有Topic下的消息全部基于顺序写,极大的提高了消息的写性能。 为了消息的消费和查找,rocketmq还引入了消息消费队列文件和索引文件。 为了避免消息不断累积,rocketmq引入了消息文件过期机制(默认保留3天)以及文件存储空间报警机制。 消费者幂等消费消息 rocketmq通过消息消费确认机制(ACK)确保消息至少被消费一次,但不保证消息不会被重复消费,也就是说,消费者可能会消费同条消息多次,这里就需要消费者消费时,逻辑上实现幂等。

  • go logo
    Go,  技术,  编程语言

    从零开始搭建go项目(gin框架)(六) – 接口实现

    本节内容,我们正式实现一个添加用户的接口,实现我们整个项目接口请求的层级。 接口代码层级 在根目录下,新创建 ./repositories 和 ./models 目录,接口请求的数据逻辑顺序如下: route -> api -> services -> repositories -> models 接口实现 创建 ./models/user.go: 创建 ./repositories/user.go: 创建./services/user.go: 增加路由,修改 ./router/router.go 接口测试 至此,一个添加用户的接口就实现了 ~

  • php logo
    PHP,  技术,  编程语言

    php 去除文件Bom头

    遇到文件处理,特别是excel文件处理时,经常会遇到bom头的问题,下面我们介绍下如何去除文件的Bom头。 代码 原理 实际应用的是sed命令: 这种方式,不需要将文件内容加载到内存里面,减少了内存的消耗以及大文件可能造成的内存超限问题。

  • go logo
    Go,  技术,  编程语言

    从零开始搭建go项目(gin框架)(五) – 支持Mysql

    本节内容,我们将mysql引入我们的框架 (本地mysql部署可参考 Mysql集群部署(主从复制)。 第一步 引入mysql相关服务 第二步 创建测试库表 第三部 对mysql进行封装 创建./library/database/mysql.go : 第四步 增加mysql配置与读取 ./conf/config.yaml, 新增 ./conf/config.go: 第五步 mysql初始化 创建文件./helpers/mysql.go: 第六步 main函数中调用 ./main.go : 至此,我们项目就已经支持mysql使用啦~,下一章我们再介绍mysql在项目中的具体使用 参考链接 https://gorm.io/