您现在的位置是:首页 > 文章详情

禁止Golang编译时“imported and not used”和“declared and not used”两种报错

日期:2019-05-11点击:412

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 
原文链接:https://my.oschina.net/chenchacha/blog/3048381
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章