如何避免“声明且未使用”的烦人错误


238

我正在学习Go,但感到有点烦人,在编译时,我不应该保留任何变量或包。

这确实让我放慢了脚步。例如,我只想声明一个新软件包并计划以后使用它,或者只是取消注释某些命令以进行测试。我总是会收到错误,需要对所有这些用法进行评论。

Go中有什么方法可以避免这种检查吗?


1
您还可以使用goimports(godoc.org/code.google.com/p/go.tools/cmd/goimports)为您自动添加/删除导入。
elithrar 2014年


3
我仍然觉得编译器选项对于“我想注释掉某些东西以帮助调试”工作流程很有用。
RJFalconer

13
此功能是浪费人们时间的好方法,哈哈,有什么意义?提交/提交代码时,没有未使用的vars是好的,但是在开发它时呢?可怕。
亚历山大·米尔斯'18

现在是2020年,我简直不敢相信他们仍然没有解决这个问题(甚至没有编译器标志)。大约5年前,我在Go中进行了一个项目,总体上喜欢这种语言,但仅因为这个原因,它对我来说是无法使用的。我编写代码的方式是不断评论/取消评论,因此Go中的“功能”使事情花了我两倍的时间...从那时起,我每隔几个月就要进行一次检查,以查看是否已经超越了理性围棋队,到目前为止还没有运气。否则,这是一门很棒的语言,我很想多使用它,但是目前它对我来说是不可用的。
Ruslan,

Answers:


234

该错误将迫使您编写更好的代码,并确保使用声明或导入的所有内容。它使阅读他人编写的代码更加容易(您始终可以确保将使用所有已声明的变量),并避免了一些可能的无效代码。

但是,如果您确实想跳过此错误,则可以使用空白标识符_):

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在以下评论中所说,您可以在FAQ中找到Go小组的正式职位:

未使用的变量的存在可能表明存在错误,而未使用的导入只会减慢编译速度。在代码树中积累足够的未使用导入,事情可能会变得很慢。由于这些原因,Go都不允许。


90
不过,这与将其注释掉并没有什么不同。而且,我知道这是为了获得更好的代码,但是如果我们可以关闭检查为什么对我们的代码进行测试,然后在我们要完成代码并将其清理干净之后再次打开此检查,会更好吗?
2014年

21
@kostix好吧..它可能不会让您放慢脚步,因为您可能是专家,但这是给我的,也是我编写代码的方式。我只是想知道是否有更好的方法。但是无论如何,感谢您的常见问题解答!通过阅读本文,我可以完全理解golang这样做的原因。
A-letubby 2014年

20
是否有命令行参数可以将其关闭?还是这是不可更改的功能?
伊桑·比林

26
FWIW,我在阅读别人的代码时遇到了麻烦,但绝对不是由于未使用符号引起的。太太,我今天花了一个小时研究这种*#%$ golang“功能”的方法。
Torsten Bronger

24
可悲的是,这个答案是正确的-但这并不能证明它的合理性。签入代码和简单执行代码之间存在天壤之别。检入代码时,我们使用linters捕获此类错误。在快速开发过程中执行时,我们没有相同的标准。将编译器与linter混淆是不可原谅的。即使是Google内部的样式警察也不会犯该错误。
特拉维斯·威尔逊

29

您可以为此使用一个简单的“空函数”,例如:

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)
}

29

根据常见问题解答

有些人要求使用编译器选项来关闭这些检查或至少将其减少为警告。但是,由于编译器选项不应影响语言的语义,并且因为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

9

到目前为止尚未提及的一个角度是用于编辑代码的工具集。

使用Visual Studio代码与扩展一起lukehobanGo会做一些自动魔术给你。转到扩展自动运行gofmtgolint等等,以及移除并添加import条目。因此,至少该部分现在是自动的。

我将承认它不是100%解决该问题的方法,但是足够有用。


8

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

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

您可以为该函数分配一个无用/空白变量,以便不再使用它

myFn := func () { }
_ = myFn
// myFn()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.