为什么我们可以有未使用的函数,但不能有未使用的变量?

huangapple go评论92阅读模式
英文:

Why can we have unused functions but we can't have unused variables?

问题

未使用的变量会阻止编译(这是一件好事),但编译器对未使用的函数并不真正关心,这是为什么呢?

英文:

Unused variables will block compiling (that's a good thing) but compiler don't really care about unused functions, is there an explanation ?

答案1

得分: 2

行为在变量和函数之间似乎是一致的 - 即使未使用,两者都允许在包级作用域中。

这段代码在没有任何问题的情况下编译通过:

package main

var v int // 未使用的变量

func f() {} // 未使用的函数

func main() {}

现在,当涉及到局部作用域时情况就不同了,未使用的变量会生成错误。对于函数字面量也是如此(在Go中不允许使用命名的嵌套函数):

func main() {
	func() {}
}
// 错误:函数字面量被计算但未使用

最后,为什么只检查局部作用域中的未使用变量?因为通常这是一个错误(例如,在Go中,由于意外使用了:=)。编译器在这里帮了我很多次。考虑以下情况:

func f() (err error) {
	if somthing {
		err := g() // err 是未使用的变量!我真正想要的是 `=`
	}
	return
}

对于全局(包级)作用域,未使用的变量和函数通常只是污染命名空间,例如,有人在重构后忘记删除它们。有一些工具可以帮助检测这些问题,例如:

  1. https://github.com/opennota/check
  2. https://github.com/alecthomas/gometalinter(使用上述包)
  3. https://github.com/remyoudompheng/go-misc/blob/master/deadcode/deadcode.go

我还找到了 Russ Cox 的一篇帖子对此问题进行了评论:

> 最近我用 gcc -Wall -Werror 写了一些 C 代码。当你只是想测试你已经完成的代码或注释掉可能引起问题的调用时,这使得原型代码有些困难。当然,对于未使用的局部变量发出警告也是一样的。不同之处在于,在 Go 中,由于 :=,未使用的局部变量很常见是一个 bug,而未使用的未导出函数很少是一个 bug。
>
> Russ

英文:

The behaviour seems consistent between variables and functions – both are allowed in a package-level scope, even if unused.

This snippet is compiling without any issues:

package main

var v int // unused variable

func f() {} // unused function

func main() {}

Now, when it comes to local scope things are different and unused variables generate errors. Same for function literals (named nested functions are not allowed in Go):

func main() {
	func() {}
}
// Error: func literal evaluated but not used

Finally, why is only local scope checked for unused variables? Because usually it's a bug (for examples, in Go, due to an accidental usage of :=). And compiler saved me many times here. Consider this:

func f() (err error) {
	if somthing {
		err := g() // err is unused variable! I really meant `=`.
	}
	return
}

For global (package-level) scopes unused variables and functions are usually just polluting the namespace as, for example, someone forgot to remove them after refactoring. There're some tools which helps detecting these, for example:

  1. https://github.com/opennota/check
  2. https://github.com/alecthomas/gometalinter (uses the previous package)
  3. https://github.com/remyoudompheng/go-misc/blob/master/deadcode/deadcode.go

I also found a post by Russ Cox commenting on the issue:

> I have been writing some C code with gcc -Wall -Werror recently. It
> makes prototyping code somewhat difficult to be told "you didn't use
> that function, go fix it" when you're just trying to test what you've
> got so far, or commenting out calls that are possibly causing trouble.
> Of course the same is true for warning about unused local variables
> too. The difference is that, in Go, because of :=, an unused local
> variable is very often a bug, while an unused unexported function is
> much less often a bug.
>
> Russ

huangapple
  • 本文由 发表于 2015年11月17日 17:35:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/33753454.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定