禁止Golang编译时“imported and not used”和“declared and not used”两种报错
Go语言在代码规范之严格是有目共睹的,引用未使用的头文件会报“imported and not used”错误,定义未使用的变量会报“declared and not used”错误。因为golang编译器只有错误没有报警,所以代码中如果有此类问题,编译就会停止。
Golang不提供语法宽容的debug模式,也就是说,无论是什么时候,Go代码都必须保持干干净净的状态。
随手注释部分变量是编码阶段的一个常用手段,Golang的编译器每每跳出来,让你把变量的定义和相关头文件的引用也通通删掉。有时候临时注释一段代码会产生一堆未引用和未定义错误,而为了解决这些错误往往又会把代码被改得面目全非。对于debug阶段的程序员来讲,有一个管得太宽的编译器是一件痛苦的事情。
好在Golang是开源的,弄一个不太折腾的Golang编译器并不困难。
修改源码
首先下载golang代码:
$ git clone https://github.com/golang/go
拉到最新分支,现在最新的版本号是1.12.5:
$ cd go $ git checkout -b debug-1.12.5 go1.12.5
未引用头文件和未定义变量错误相关的代码在下面4个文件中:
- src/cmd/compile/internal/gc/main.go
- src/cmd/compile/internal/gc/subr.go
- src/cmd/compile/internal/gc/swt.go
- src/cmd/compile/internal/gc/walk.go
用 if false {} 把相关代码注释掉。
具体内容可以看这个patch:
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 98ff2a3d27..2bb2e6fe37 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -1246,11 +1246,13 @@ func pkgnotused(lineno src.XPos, path string, name string) { if i := strings.LastIndex(elem, "/"); i >= 0 { elem = elem[i+1:] } + if false { if name == "" || elem == name { yyerrorl(lineno, "imported and not used: %q", path) } else { yyerrorl(lineno, "imported and not used: %q as %s", path, name) } + } } func mkpackage(pkgname string) { diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 2a976dc4f0..be662c3df8 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -291,10 +291,12 @@ func importdot(opkg *types.Pkg, pack *Node) { n++ } + if false { if n == 0 { // can't possibly be used - there were no symbols yyerrorl(pack.Pos, "imported and not used: %q", opkg.Path) } + } } func nod(op Op, nleft, nright *Node) *Node { diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go index cc9a8f8b2c..6f27447bb0 100644 --- a/src/cmd/compile/internal/gc/swt.go +++ b/src/cmd/compile/internal/gc/swt.go @@ -70,12 +70,14 @@ func typecheckswitch(n *Node) { if t != nil && !t.IsInterface() { yyerrorl(n.Pos, "cannot type switch on non-interface value %L", n.Left.Right) } + if false { if v := n.Left.Left; v != nil && !v.isBlank() && n.List.Len() == 0 { // We don't actually declare the type switch's guarded // declaration itself. So if there are no cases, we // won't notice that it went unused. yyerrorl(v.Pos, "%v declared and not used", v.Sym) } + } } else { // expression switch top = ctxExpr diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 509579d21f..92ad512d37 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -41,6 +41,7 @@ func walk(fn *Node) { } } + if false { for _, ln := range fn.Func.Dcl { if ln.Op != ONAME || (ln.Class() != PAUTO && ln.Class() != PAUTOHEAP) || ln.Sym.Name[0] == '&' || ln.Name.Used() { continue @@ -55,6 +56,7 @@ func walk(fn *Node) { yyerrorl(ln.Pos, "%v declared and not used", ln.Sym) } } + } lineno = lno if nerrors != 0 {
生成debug版编译器
编译debug版Golang:
$ cd src $ GOOS=linux GOARCH=amd64 ./bootstrap.bash
../../目录下会生成两个文件:
$ ls ../../ go/ go-linux-amd64-bootstrap/ go-linux-amd64-bootstrap.tbz
其中go-linux-amd64-bootstrap就是debug版的Golang。
在/usr/bin下面创建一个可执行文件debuggo,文件中的GOROOT指向go-linux-amd64-bootstrap目录:
#!/bin/bash GOROOT=/PATH-TO-GOLANG/go-linux-amd64-bootstrap ${GOROOT}/bin/go $@
好了,大功告成,debug的时候执行:
$ debuggo build
编译器果然就老实了很多。
不过要发布的时候记得用官方的编译器做语法检查:
$ go build -a

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
HTTP的发展历史 【积一时之跬步,臻千里之遥程】
http版本导图 2. HTTP版本之概念篇 HTTP(超文本传输协议),是互联网上应用最为广泛的一种网络协议,定义了浏览器怎样向服务器请求文档,以及服务器怎样把文档传送给浏览器。HTTP基于TCP/IP协议的应用层协议,它不涉及数据包传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。 HTTP/0.9版本篇 要点 客户端向服务器请求网页,服务器只能回应HTML格式的字符串,不能回应别的格式。 只有GET方式 服务器发送完毕。就关闭TCP连接 缺点 每个TCP连接只能发送一个请求;发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接 TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢 网页加载的外部资源越多,性能就越差 只有一种请求方式 HTTP/1.0版本篇 要点 任何格式的内容都可以发送。互联网不仅可以传输文字,还可以传输图像,视频,二进制文件。(由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。CONTENT-ENCODING字段说明数据压缩的方法 压缩的方式有(可以并列多个,用逗号隔开): CONTENT-EN...
- 下一篇
Go 你不知道的简短变量声明约束
前言 虽然简短变量声明这个语法糖用起来很方便,但有时也会给你一个意外也可能带你掉入陷阱。 我曾因滥用这个:=语法糖,发生过一次故障,所以才认真研究了一下它的原理和规则,大家可以做为参考。 规则 规则一: 多变量赋值可能会重新声明 我们知道使用:=一次可以声明多个变量,像下面这样: field1, offset := nextField(str, 0) 上面代码定义了两个变量,并用函数返回值进行赋值。 如果这两个变量中的一个再次出现在:=左侧就会重新声明。像下面这样: field1, offset := nextField(str, 0) field2, offset := nextField(str, offset) offset被重新声明。 重新声明并没有什么问题,它并没有引入新的变量,只是把变量的值改变了,但要明白,这是Go提供的一个语法糖。 当:=左侧存在新变量时(如field2),那么已声明的变量(如offset)则会被重新声明,不会有其他额外副作用。 当:=左侧没有新变量是不允许的,编译会提示no new variable on left side of :=。 我们所说的重...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Red5直播服务器,属于Java语言的直播服务器
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境