ChatGPT解决这个技术问题 Extra ChatGPT

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

go

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

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

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

我仍然觉得编译器选项对于“我想注释掉一些东西以帮助调试”工作流程很有用。
这个功能是浪费人们时间的好方法哈哈,有什么意义?当您提交/交付代码时,没有未使用的变量很好,但是在开发时呢?可怕。
现在是 2020 年,我不敢相信他们还没有解决这个问题(即使没有编译器标志)。大约 5 年前,我在 Go 中做了一个项目,总体上喜欢这种语言,但仅仅因为这个,它对我来说无法使用。我编码的方式我经常评论/取消评论的东西,所以 Go 中的这个“功能”让我花费了两倍的时间......从那时起我每隔几个月就会检查一次,看看是否有一种理性感已经超越围棋队,到目前为止还没有运气……糟透了。否则它是一门很棒的语言,我很想更多地使用它,但目前它对我来说不可用。
@RickO'Shea 将未使用的变量分配给一次性变量 _ 仍然是一项非常繁琐的工作,显然会破坏开发人员的流程。每次您注释掉某些内容时,您都需要去存根所有 declared but not used 错误。任何团队都可以将标准和样式检查作为提交挂钩或 CI/Gate 工作的一部分来实施。这里缺乏给开发人员的代理权是一种傲慢,而且还迫使我们编写 worse 代码以便能够将事情分开。 goimports 解决了导入问题,变量应该可以接受编译器标志。
未使用变量的一个用例是在调试时让它们显示在手表中。我经常使用它,并且不得不使用 _ 来解决它真的很烦人。

F
Flimzy

该错误会迫使您编写更好的代码,并确保使用您声明或导入的所有内容。它使阅读其他人编写的代码变得更容易(您始终确信所有声明的变量都会被使用),并避免一些可能的死代码。

但是,如果你真的想跳过这个错误,你可以使用 blank identifier (_) :

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 团队 in the FAQ 的官方立场:

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


尽管如此,这与将其注释掉并没有太大区别。而且,我知道这是为了更好的代码,但是如果我们可以关闭检查为什么要对我们的代码进行测试,然后在我们想要完成代码并使其干净之后再次打开此检查会更好吗?
FWIW,我在阅读其他人的代码时遇到了麻烦,但绝对不是因为未使用的符号。 OTOH,我今天浪费了一个小时来研究处理这个 *#%$ golang“功能”的方法。
可悲的是,这个答案是正确的——但这并不能证明它是正确的。签入代码和简单地执行代码之间存在天壤之别。当我们签入代码时,我们使用 linter 来捕获这种错误。当我们在快速开发过程中执行时,我们没有相同的标准。将编译器与 linter 混淆是不可原谅的。即使是谷歌内部的风格警察也不会犯这个错误。
这是 Go 团队的愚蠢决定。特别是在尝试调试时。
让编译器将此视为错误是不可原谅的。可以说这个问题是 linter 和代码样式规范的范围,但最终每次我进行一些快速调试并注释掉几行代码时,都会出现将其作为编译错误的愚蠢。在我编译之前必须通过注释掉的块并注释掉在那里消耗的所有声明,这是一种令人作呕的浪费。这将一个 2 秒的调试习惯变成了一个可以燃烧 30 倍那么长时间的 slog。语言规范没有必要将这条法令强加给我们。
M
Martin Tournoij

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

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

also a package for this,因此您不必每次都定义 Use 函数:

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

func main() {
  // [..]

  xulu.Use(a, b, c)
}

有没有办法自动使用所有声明的 val?出于开发目的,这个问题真的很烦人 =/
看来循环是不必要的,请参阅下面的这个答案stackoverflow.com/a/62951339/722796
C
Community

根据the 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

“Go 编译器不报告警告,只报告阻止编译的错误。”有用的信息,但语言作者的方法很糟糕
是的,很难同意。我正在自己测试 Go,遇到这些“错误”不是因为代码需要修复,而是因为代码还没有完成。如果我想在调试过程中注释掉一些东西......由于未使用的变量,我需要重新处理其他部分。
c
chuacw

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

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

然后你可以像这样使用它:

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

它的好处是,你可以将任何东西传递给 UNUSED。

是不是比下面的好?

_, _, _ = x, y, z

这取决于你。


我发现这种方法比空白标识符更有用......当我在 go 中开发时,我喜欢尽可能早且尽可能频繁地运行我的代码......让一些变量“未使用”对我来说更有用我的最后一行,而不是注释掉可能无法按我预期工作的整个块。
这是一个很棒的解决方案
非常简洁,并且很容易将该关键字添加到您的 linting 系统中,以确保您在实际需要时“修复”它。
m
max pleaner

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

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

您可以为函数分配一个无用/空白变量,使其不再被使用:

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

m
miltonb

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

使用 Visual Studio Code 以及来自 lukehoban 的名为 Go 的扩展程序将为您带来一些自动魔法。 Go 扩展程序会自动运行 gofmtgolint 等,并删除和添加 import 个条目。所以至少那部分现在是自动的。

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


m
maxime

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

评论服务的使用触发了很多级联错误,所以我没有评论我使用了一个条件

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

P
Petrus Theron

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


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅