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

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

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