听说它可以让代码更优雅

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

言归正传,相信很多程序员朋友都听说过静态代码检查工具这个概念,它可能是我们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)^

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

小总结

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

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

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

相关文章

RK3588+MIPI+GMSL+AI摄像机:自动车载4/8通道GMSL采集/边缘计算盒解决方案

RK3588作为目前市面能买到的最强国产SOC,有强大的硬件配置。在智能汽车飞速发展,对图像数据矿场要求越来越多的环境下,如何高效采集数据,或者运行AI应用,成为刚需。 推出的4/8通道GMSL采集/边缘计算盒产品满足这些需求…

Spring验证码

前言:使用Hutool 1.什么是Hutool? 2.代码复制到test类中 3.代码爆红,说明需要引入依赖 4.根据名取Maven仓库相关依赖 5.在pom.xml文件中进行配置 6.引入成功 7. 运行程序 打开d盘,发现已经生成了验证码的图片,路径在…

Codeforces Round 654 (Div. 2) C. A Cookie for You (模拟)

我认为这道题就是个脑筋急转弯。 首先我们知道当a b < n m的时候&#xff0c;饼干总数都不够人的总数&#xff0c;那肯定是NO。 并且注意题干&#xff0c;我们可以得知当a b的时候&#xff0c;第一类和第二类人可以任意选两种饼干中的一种。 之后我们可以分类讨论一下。 …

网格布局 HTML CSS grid layout demo

文章目录 页面效果代码 (HTML CSS)参考 页面效果 代码 (HTML CSS) <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"…

[ BLE4.0 ] 伦茨ST17H66开发-串口UART0的接收与发送

目录 一、前言 二、实现步骤 1.设置回调函数 2.关闭睡眠模式 三、效果展示 四、工程源代码 一、前言 串口通信在任何一款单片机开发中都是尤为重要的。本文涉及的开发所使用的例程依然是基于[ BLE4.0 ] 伦茨ST17H66开发-OSAL系统中添加自己的Task任务文章的工程源码&#x…

windows@powershell@任务计划@自动任务计划@taskschd.msc.md

文章目录 使用任务计划windows中的任务计划任务计划命令行程序开发windows 应用中相关api传统图形界面FAQ schtasks 命令常见用法创建计划任务删除计划任务查询计划任务修改计划任务运行计划任务 PowerShell ScheduledTasks常用 cmdlet 简介1. Get-ScheduledTask2. Register-Sc…

Git远程仓库推送

这里我只连接了两个站点的远程仓库&#xff0c;一个是国内的Gitee&#xff0c;另一个是Github&#xff0c;这两个站点的连接方式主要有两种&#xff0c;第一种就是通过https来连接远程仓库&#xff0c;另一种是通过ssh公钥来连接&#xff0c;这两个站点练接的大致过程都是一样的…

我出一道面试题,看看你能拿 3k 还是 30k!

大家好&#xff0c;我是程序员鱼皮。欢迎屏幕前的各位来到今天的模拟面试现场&#xff0c;接下来我会出一道经典的后端面试题&#xff0c;你只需要进行 4 个简单的选择&#xff0c;就能判断出来你的水平是新手&#xff08;3k&#xff09;、初级&#xff08;10k&#xff09;、中…

4 款最佳 C# 无头浏览器

摘要&#xff1a; 在当今大数据时代&#xff0c;高效的数据采集成为众多项目的关键一环。对于偏好C#语言的开发者而言&#xff0c;无头浏览器是实现网页自动化交互、数据抓取的强大工具。本文将深入探讨四款顶尖的C#无头浏览器库&#xff0c;分析它们的特性和应用场景&#xf…

怎么把C盘分成两个盘?让C盘分区更简单,赶快试试!

在日常使用电脑的过程中&#xff0c;有时我们可能希望将C盘分割成两个独立的分区&#xff0c;以便更好地管理文件和数据。这种操作需要谨慎进行&#xff0c;因为错误的分区操作可能导致数据丢失。那么&#xff0c;我们该怎么把C盘分成两个盘呢&#xff1f;下面&#xff0c;我将…

lua 游戏架构 之 游戏 AI (六)ai_auto_skill

定义一个为ai_auto_skill的类&#xff0c;继承自ai_base类。ai_auto_skill类的目的是在AI自动战斗模式下&#xff0c;根据配置和条件自动选择并使用技能。 lua 游戏架构 之 游戏 AI &#xff08;一&#xff09;ai_base-CSDN博客文章浏览阅读379次。定义了一套接口和属性&#…

vue3在元素上绑定自定义事件弹出虚拟键盘

最近开发中遇到一个需求: 焊接机器人的屏幕上集成web前端网页, 但是没有接入键盘。这就需要web端开发一个虚拟键盘,在网上找个很多虚拟键盘没有特别适合,索性自己写个简单的 图片: 代码: (代码可能比较垃圾冗余,也没时间优化,凑合看吧) 第一步:创建键盘组件 为了方便使用…

3.2.微调

微调 ​ 对于一些样本数量有限的数据集&#xff0c;如果使用较大的模型&#xff0c;可能很快过拟合&#xff0c;较小的模型可能效果不好。这个问题的一个解决方案是收集更多数据&#xff0c;但其实在很多情况下这是很难做到的。 ​ 另一种方法就是迁移学习(transfer learning…

c++如何理解多态与虚函数

目录 **前言****1. 何为多态**1.1 **编译时多态**1.1.1 函数重载1.1.2 模板 **1.2 运行时多态****1.2.1 虚函数****1.2.2 为什么要用父类指针去调用子类函数** **2. 注意****2.1 基类的析构函数应写为虚函数****2.2 构造函数不能设为虚函数** **本文参考** 前言 在学习 c 的虚…

打造重庆市数字化教育“新名片”,广阳湾珊瑚中学凭实力“出圈”!

分布于教学楼连廊顶部的智能照明设备,根据不同的时间和场景需求自动调节灯光亮度和开关状态;安装于各个教室内的智能黑板、学校同步时钟、学生互动设备,在极简以太全光网的赋能下,为师生提供丰富的教学体验与学习支持......行走于重庆市广阳湾珊瑚中学,像是与充满科技感的“校园…

病理AI领域的基础模型汇总|顶刊专题汇总·24-07-26

小罗碎碎念 本期文献主题&#xff1a;病理AI领域的最新基础模型 今天的推文是一期生日特辑&#xff0c;定时在下午六点二十一分发表&#xff08;今天农历六月二十一&#xff0c;哈哈&#xff09;&#xff0c;算是自己给自己的24岁生日礼物&#xff0c;希望24岁这一年&#xff0…

ollama本地部署大语言模型记录

目录 安装Ollama更改模型存放位置 拉取模型GemmaMistralQwen1.5(通义千问)codellama 部署Open webui测试性能知识广度问题1问题2 代码能力总结 最近突然对大语言模型感兴趣 同时在平时的一些线下断网的CTF比赛中&#xff0c;大语言模型也可以作为一个能对话交互的高级知识检索…

SSRF中伪协议学习

SSRF常用的伪协议 file:// 从文件系统中获取文件内容,如file:///etc/passwd dict:// 字典服务协议,访问字典资源,如 dict:///ip:6739/info: ftp:// 可用于网络端口扫描 sftp:// SSH文件传输协议或安全文件传输协议 ldap://轻量级目录访问协议 tftp:// 简单文件传输协议 gopher…

【JavaScript】函数声明和函数表达式的区别

文章目录 一、函数声明1. 定义方式2. 作用域提升&#xff08;Hoisting&#xff09;3. 块级作用域 二、函数表达式1. 定义方式2. 作用域提升&#xff08;Hoisting&#xff09;3. 自引用 三、其他区别1. 函数名2. 可读性和代码组织3. 使用场景 四、总结函数声明函数表达式 在Java…

【大模型系列】Video-LaVIT(2024.06)

Paper&#xff1a;https://arxiv.org/abs/2402.03161Github&#xff1a;https://video-lavit.github.io/Title&#xff1a;Video-LaVIT: Unified Video-Language Pre-training with Decoupled Visual-Motional TokenizationAuthor&#xff1a;Yang Jin&#xff0c; 北大&#x…