当前位置: 首页 > news >正文

听说它可以让代码更优雅

一提到静态代码检查工具这个词应该比较好理解,所谓静态代码检查工具就是检查静态代码的工具,完美~

言归正传,相信很多程序员朋友都听说过静态代码检查工具这个概念,它可能是我们IDE里的某一个插件,可能是计算机中的一个程序,还可能是Git提交后的一个流程,如果是对代码要求比较高的个人或组织,静态代码检查工具则是一个绕不开的东西。

一个事物的出现必然是有所需求的,那么我们不妨先思考一下,为什么需要静态代码检查工具?

先抛开这个问题本身,我们从编译器的错误检查开始。

编译器:最严重代码的问题我替你规避

大家都知道我们写的代码是需要通过编译器编译成中间代码或可执行文件的,比如Java程序代码会由Java编译器编译成class文件,由JVM执行,Go代码会由Go编译器编译成二进制文件直接执行,中间都会有一个编译的过程,在编译原理中会有两个比较重要的流程——词法分析和语法分析。先说下词法分析和语法分析主要是用来做什么的:

词法分析是编译过程的第一步,其主要作用和特点如下:

  • 扫描源程序:词法分析器负责读入源程序的字符流,这是编译过程的输入。
  • 识别单词符号:根据源语言的词法规则,词法分析器将字符流分解并识别出各个单词符号。单词是源程序中的最小语义单位,如关键字、标识符、常数、运算符等。
  • 输出记号序列:词法分析器将识别出的单词符号转换成相应的记号(token)序列,作为语法分析的输入。每个记号通常包括一个词法单元名称(如关键字、标识符等)和一个可选的属性值(如标识符的名称、常数的值等)。
  • 过滤空白和注释:词法分析器还会跳过源程序中的空白字符(如空格、制表符等)和注释,这些对语法分析来说是无意义的。
  • 错误检测:词法分析器能够识别并报告词法错误,即非法的字符或单词符号,如非法字符、未识别的关键字等。

语法分析是在词法分析的基础上进行的,其主要作用和特点如下:

  • 分析语法结构:语法分析器根据语言的语法规则,对词法分析器输出的记号序列进行分析,以识别出各种语法单位,如表达式、语句、函数等。
  • 构建语法树:在语法分析过程中,通常会构建一棵语法树来表示源程序的语法结构。语法树的叶子节点通常对应于记号,而非叶子节点则对应于语法单位。
  • 错误检测和处理:语法分析器能够识别并报告语法错误,即不符合语法规则的记号序列。这些错误通常包括括号不匹配、缺少分号、语法单位使用不当等。
  • 为后续阶段做准备:语法分析的结果(如语法树)将作为后续阶段(如语义分析、代码生成等)的输入。通过语法分析,编译器能够确保源程序在语法上是正确的,从而可以进一步进行语义分析和代码生成等工作。

词法分析和语法分析是编译过程中不可或缺的两个阶段。词法分析负责将源程序的字符流转换成记号序列,而语法分析则根据语法规则对记号序列进行分析,以构建出源程序的语法结构。这两个阶段共同为后续的编译工作打下了坚实的基础,确保了编译过程的顺利进行。

现在我们知道了,词法分析和语法分析有一个共同的作用:错误监测

举个例子,我们使用Go中一个fmt包中不存在的函数:

package mainimport "fmt"func main() {fmt.Printlnx("Hello World")
}

执行后报错,原因很简单,因为函数的单词拼错了:

.\main.go:6:6: undefined: fmt.Printlnx

再有一个例子:

package mainimport "fmt"func main() {fmt.Println(str)str := "Hello World"
}

执行后同样报错,因为在程序中我们规定语法是先声明后使用,这段代码却是先使用后声明

.\main.go:6:14: undefined: str
.\main.go:7:2: str declared and not used

这两段代码其实主要是想阐述一件事:重大的程序问题编译器层面直接就不会编译通过。

静态代码检查工具:代码不优雅的地方我给你指出

那么有没有编译器发现不了的程序问题? 答案肯定是有的,举例子:

看这段代码:

package mainimport "fmt"func main() {str := "Hello World"fmt.Printf("%d \n",str)
}

一个很显然的问题,字符串应该使用%s进行转义,但该程序中使用的是表示整型变量的%d,但这个问题如果直接执行的话并不会报错,而是会打印出如下代码:

%!d(string=Hello World)

虽然我们写错了,但是Go程序还是会把我们想打印的数据打印出现并标记正确的类型,这个赞我点给Go的开发者!

还有这个:

package mainfunc hello() (string, error) {return "Hello", nil
}func main() {hello()
}

从优雅的角度来讲,我们应该去认真处理每个函数中的错误返回值,但是以上示例中并没有处理,编译器也编译通过了,这样就导致程序中一旦真的返回了错误,那么排查问题可能就不太方便。

除了以上两个示例,Go程序中还要很多常见的编码问题需要注意,在大型项目中我们不可能逐行代码的去看,因此衍生出了静态代码检查工具这个东西。回答文章开头的问题,进行静态代码检查的原因主要有以下几点:

提高代码质量。 静态代码检查能够在不运行代码的情况下,通过自动化的方式分析代码,帮助开发者及时发现并修复潜在的缺陷以及不符合编码规范的问题。这有助于提升代码的整体质量,减少因代码问题导致的错误和故障。

降低维护成本。产品是资产,代码是负债,因为代码越多就一定程度上意味着维护成本越高。 高质量的代码意味着更低的维护成本。通过静态代码检查,开发者可以在早期发现并解决潜在问题,避免在后期测试和维护阶段投入更多的时间和资源。除此之外,还可以确保所有成员都遵循相同的编码规范,减少因风格不一致而导致的代码合并冲突。

Go语言如何进行静态代码检查

Go语言作为一门非常简单的编程语言,语法可以非常灵活,静态代码检查的方式也非常多,主要有以下几种方式:

使用内置的go vet工具go vet是Go语言内置的一个静态分析工具,它可以帮助开发者检查Go代码中的潜在问题,如未使用的变量、错误的使用标志位等。

使用golint工具golint是一个用于Go代码的Lint工具,它可以帮助开发者找出一些可疑的或者不规范的代码写法,如导出的函数没有注释、变量名不符合规范等,但本项目官方已经不再维护。

使用第三方静态分析工具:Go语言社区还提供了许多第三方静态分析工具,如staticcheckerrcheck等。这些工具通常具有更丰富的功能和更强大的检测能力,可以帮助开发者更全面地检查代码中的潜在问题。

集成到持续集成/持续部署(CI/CD)流程中:为了自动化地进行静态代码检查,开发者可以将静态分析工具集成到项目的CI/CD流程中。每次代码提交或合并时,都会自动运行静态检查工具,确保代码质量符合要求。

使用IDE插件:如GoLand、Visual Studio Code在的一些代码检查插件可以在编写代码的过程中实时提供静态检查反馈,帮助开发者及时发现并修复问题。

现在有哪些工具我们大概知道了,怎么用具体还是要试一试,比如刚刚的这段代码,我们使用go vet工具检查一下:

package mainimport "fmt"func main() {str := "Hello World"fmt.Printf("%d \n",str)
}

使用命令go vet main.go输出结果,可以看出它会把问题表达的很清楚:

.\main.go:7:2: fmt.Printf format %d has arg str of wrong type string

对于第二段代码,我们也可以有一个三方插件来进行代码检查,安装:go install github.com/kisielk/errcheck@latest

package mainfunc hello() (string, error) {return "Hello", nil
}func main() {hello()
}

然后使用命令errcheck main.go,就会输出如下来告诉你哪行代码哪个方法没有处理错误返回值

main.go:8:7:    hello()
最好用的Go静态代码检查工具:golangci-lint

golangci-lint 可以说是一个大一统,它几乎把所有最有用的Go静态代码检查工具进行统一,并且还支持在CI/CD中使用。

官网:https://golangci-lint.run

Github:https://github.com/golangci/golangci-lint

我们可以使用命令golangci-lint help linters查看它都支持哪些静态检查工具(打印很多没截全):

可以看到有些是默认支持,有些是默认关闭支持的,我们不妨来试一下它和上面的两个工具有什么不同,我们将上面的两个代码示例合并到一起执行,运行命令golangci-lint run main.go

main.go:13:7: Error return value is not checked (errcheck)hello()^
main.go:11:2: printf: fmt.Printf format %d has arg str of wrong type string (govet)fmt.Printf("%d \n",str)^

可以看出这个工具打印的提升更加精准。后面如果想要继续深入可以阅读一下官方文档。

小总结

总的来说,静态代码检查工具是一个能够提升我们代码质量的工具,可以发现编译器发现不了的问题。这些工具的使用可以显著提高软件质量,所以大家赶快掌握起来,写出更优雅的代码!

相关文章:

听说它可以让代码更优雅

一提到静态代码检查工具这个词应该比较好理解,所谓静态代码检查工具就是检查静态代码的工具,完美~ 言归正传,相信很多程序员朋友都听说过静态代码检查工具这个概念,它可能是我们IDE里的某一个插件,可能是计算机中的一…...

自写ApiTools工具,功能参考Postman和ApiPost

近日在使用ApiPost的时候,发现新版本8和7不兼容,也就是说8不支持离线操作,而7可以。 我想说,我就是因为不想登录使用才从Postman换到ApiPost的。 众所周知,postman时国外软件,登录经常性抽风,…...

《深入浅出WPF》学习笔记一.解析WPF程序

《深入浅出WPF》学习笔记一.解析WPF程序 visual studio帮助我们做了那些事情 引用文件 输出文件类型 按照最原始的方式,我们需要手动打开编译器命令行,使用命令引用类库将代码编译成目标文件。 visual studio会根据我们选择的项目模板,自动…...

Scrapy框架中,如何有效地管理和维护爬虫的日志记录?

在Scrapy框架中,日志记录是监控爬虫行为和调试问题的重要手段。合理地管理和维护爬虫的日志记录,可以帮助开发者更好地了解爬虫的运行状态,并及时发现和解决问题。以下是一些有效管理和维护Scrapy爬虫日志记录的技巧: 1. 配置日志…...

Laravel Sanctum:简化无状态API认证的新纪元

Laravel Sanctum:简化无状态API认证的新纪元 在现代Web应用中,API的安全认证是一个核心需求。Laravel Sanctum是一个轻量级的认证解决方案,专为Laravel开发的单页应用(SPA)、移动应用和API而生。它提供了一种简单而灵…...

OCC BRepOffsetAPI_ThruSections使用

目录 一、BRepOffsetAPI_ThruSections简介 二、功能与特点 三、应用场景 四、示例 一、BRepOffsetAPI_ThruSections简介 在Open CASCADE Technology (OCCT) 中,BRepOffsetAPI_ThruSections 类是用来通过放样生成一个实体或者一个面壳(Shell)。当使用这个类时,isSolid 参…...

driver. findElement()vs Selenium中的Webelement. findElement()

Selenium是一个开源工具,可以自动化Web浏览器并帮助测试Web应用程序。它是Web应用程序测试中使用最广泛的工具之一。在Selenium中,两种常用的查找Web元素的方法是driver.findElement和WebElement.findElement。本文将讨论它们之间的差异。 findElement() 方法声明 WebEl…...

jquery图片懒加载

HTML、 <div><img class"lazyload" alt"" width"1000" data-original"/skin/default/images/BB2.jpg" src"默认图片地址"/><img class"lazyload" alt"" width"1000" data-…...

【端口】-

端口总体上分为硬件端口和软件端口 硬件端口&#xff1a;路由器或者交换机上的硬件端口&#xff0c;硬件端口是不同硬件设备进行交互的接口 软件端口&#xff1a;应用层的各种协议进程与运输实体进行层间交互的一种地址...

【研发日记】Matlab/Simulink技能解锁(十一)——Stateflow中的en、du、ex应用对比

文章目录 前言 项目背景 en类型 du类型 ex类型 组合类型 分析和应用 总结 参考资料 前言 见《【研发日记】Matlab/Simulink技能解锁(六)——六种Simulink模型架构》 见《【研发日记】Matlab/Simulink技能解锁(七)——两种复数移相算法》 见《【研发日记】Matlab/Simul…...

《学会 SpringMVC 系列 · 剖析篇(上)》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

【Vulnhub系列】Vulnhub_SecureCode1靶场渗透(原创)

【Vulnhub系列靶场】Vulnhub_SecureCode1靶场渗透 原文转载已经过授权 原文链接&#xff1a;Lusen的小窝 - 学无止尽&#xff0c;不进则退 (lusensec.github.io) 一、环境配置 1、从百度网盘下载对应靶机的.ova镜像 2、在VM中选择【打开】该.ova 3、选择存储路径&#xff0…...

【C语言】结构体详解 -《探索C语言的 “小宇宙” 》

目录 C语言结构体&#xff08;struct&#xff09;详解结构体概览表1. 结构体的基本概念1.1 结构体定义1.2 结构体变量声明 2. 结构体成员的访问2.1 使用点运算符&#xff08;.&#xff09;访问成员输出 2.2 使用箭头运算符&#xff08;->&#xff09;访问成员输出 3. 结构体…...

基于DTW距离的KNN算法实现股票高相似筛选案例

使用DTW算法简单实现曲线的相似度计算-CSDN博客 前文中股票高相关k线筛选问题的延伸。基于github上的代码迁移应用到股票高相关预测上。 这里给出一个相关完整的代码实现案例。 1、数据准备 假设你已经有了一些历史股票的k线数据。如果数据能打标哪些股票趋势是上涨的、下跌…...

GD32 - IIC程序编写

一、初始化 理论知识链接&#xff1a; IIC理论知识 二、代码实现 1、SDA和SCL设置成开漏输出模式 开漏输出的作用&#xff1a; 因为IIC总线是一种双向的通信协议&#xff0c;需要使用开漏输出实现共享总线。开漏输出类似于一种线与的方式&#xff0c;即无论总线上哪个设备…...

将项目部署到docker容器上

通过docker部署前后端项目 前置条件 需要在docker中拉去jdk镜像、nginx镜像 docker pull openjdk:17 #拉取openjdk17镜像 docker pull nginx #拉取nginx镜像部署后端 1.打包后端项目 点击maven插件下面的Lifecycle的package 对后端项目进行打包 等待打包完成即可 2.将打…...

免费【2024】springboot宠物美容机构CRM系统设计与实现

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…...

搞懂数据结构与Java实现

文章链接&#xff1a;搞懂数据结构与Java实现 (qq.com) 代码链接&#xff1a; Java实现数组模拟循环队列代码 (qq.com) Java实现数组模拟栈代码 (qq.com) Java实现链表代码 (qq.com) Java实现哈希表代码 (qq.com) Java实现二叉树代码 (qq.com) Java实现图代码 (qq.com)...

Stable Diffusion 图生图

区别于文生图&#xff0c;所谓的图生图&#xff0c;俗称的垫图&#xff0c;就是比文生图多了一张参考图&#xff0c;由参考一张图来生成图片&#xff0c;影响这个图片的要素不仅只靠提示词了&#xff0c;还有这个垫图的因素&#xff0c;这个区域就上上传垫图的地方&#xff0c;…...

语言转文字

因为工作原因需要将语音转化为文字&#xff0c;经常搜索终于找到一个免费的好用工具&#xff0c;记录下使用方法 安装Whisper 搜索Colaboratory 右上方链接服务 执行 !pip install githttps://github.com/openai/whisper.git !sudo apt update && sudo apt install f…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...