如何避免恼人的“声明而未使用”错误

我正在学习Go,但我觉得在编译时,我不应该留下任何未使用的变量或包,这有点烦人。

这真的让我慢下来了。例如,我只想声明一个新包并计划稍后使用它,或者只是取消某些命令的注释以进行测试。我总是得到错误,需要注释所有这些使用。

在围棋中,有什么方法可以避免这种检查吗?

176725 次浏览

这个错误迫使您编写更好的代码,并确保使用您声明或导入的所有内容。它使阅读其他人编写的代码更容易(您总是可以确定所有声明的变量都将被使用),并避免一些可能的死代码。

但是,如果你真的想跳过这个错误,你可以使用空白标识符 (_):

package main


import (
"fmt" // imported and not used: "fmt"
)


func main() {
i := 1 // i declared and not used
}

就变成了

package main


import (
_ "fmt" // no more error
)


func main() {
i := 1 // no more error
_ = i
}

正如kostix在下面的评论中所说,你可以找到Go团队常见问题解答的官方立场:

未使用变量的存在可能表明存在错误,而未使用的导入只会降低编译速度。在代码树中积累足够多的未使用的导入,事情就会变得非常缓慢。由于这些原因,围棋两者都不允许。

你可以使用一个简单的“null函数”,例如:

func Use(vals ...interface{}) {
for _, val := range vals {
_ = val
}
}

你可以这样使用:

package main


func main() {
a := "declared and not used"
b := "another declared and not used"
c := 123


Use(a, b, c)
}

这也是一个包,所以你不必每次都定义Use函数:

import (
"github.com/lunux2008/xulu"
)


func main() {
// [..]


xulu.Use(a, b, c)
}

根据FAQ:

有些人要求一个编译器选项来关闭这些检查,或者至少把它们减少到警告。但是没有添加这样的选项,因为编译器选项不应该影响语言的语义,而且Go编译器不报告警告,只报告阻止编译的错误。

没有警告有两个原因。首先,如果它值得抱怨,那么它就值得在代码中修复。(如果不值得修复,那就不值一提。)其次,让编译器生成警告可以鼓励实现对可能使编译吵闹的弱用例发出警告,掩盖应该修复的真正错误。

我并不一定同意这个观点,原因有很多,不值得细讲。它就是这样,而且在不久的将来不太可能改变。

对于包,有goimports工具可以自动添加丢失的包并删除不使用的包。例如:

# Install it
$ go get golang.org/x/tools/cmd/goimports


# -w to write the source file instead of stdout
$ goimports -w my_file.go

你应该能够从任何一个不错的编辑器运行这个,例如Vim:

:!goimports -w %

goimports页面为其他编辑器列出了一些命令,并且您通常将其设置为在将缓冲区保存到磁盘时自动运行。

注意,goimports也将运行gofmt


如前所述,对于变量,最简单的方法是(临时)将它们赋值给_:

// No errors
tasty := "ice cream"
horrible := "marmite"


// Commented out for debugging
//eat(tasty, horrible)


_, _ = tasty, horrible

目前还没有提到的一个角度是用于编辑代码的工具集。

使用Visual Studio代码lukehoban的扩展名为Go将为你做一些自动魔术。Go扩展自动运行gofmtgolint等,和删除并添加import条目。所以至少这部分是自动的。

我承认这不是问题的100%解决方案,但无论如何足够有用。

如果其他人很难理解这一点,我认为用非常直接的术语解释它可能会有所帮助。如果你有一个你不使用的变量,例如你已经注释掉调用的函数(一个常见的用例):

myFn := func () { }
// myFn()

你可以给函数赋值一个无用的/空白变量,这样它就不再是未使用的了:

myFn := func () { }
_ = myFn
// myFn()

当我想在处理代码的另一部分时暂时禁用发送电子邮件时,我遇到了这个问题。

注释服务的使用会触发很多级联错误,所以我使用了一个条件而不是注释

if false {
// Technically, svc still be used so no yelling
_, err = svc.SendRawEmail(input)
Check(err)
}

2年前我在学习围棋的时候遇到了这个问题,所以我声明了自己的函数。

// UNUSED allows unused variables to be included in Go programs
func UNUSED(x ...interface{}) {}

然后你可以这样使用它:

UNUSED(x)
UNUSED(x, y)
UNUSED(x, y, z)

它最大的好处是,你可以把任何东西都变成闲置的。

它比下面的好吗?

_, _, _ = x, y, z

这取决于你。

据我所知,Go编译器中的这些线看起来像注释掉的那些。您应该能够构建自己的工具链,忽略这些适得其反的警告。