ChatGPT解决这个技术问题 Extra ChatGPT

How to avoid annoying error "declared and not used"

go

I'm learning Go but I feel it is a bit annoying that when compiling, I should not leave any variable or package unused.

This is really quite slowing me down. For example, I just wanted to declare a new package and plan to use it later or just uncomment some command to test. I always get the error and need to go comment all of those uses.

Is there any way to avoid this kind of check in Go?

I still feel a compiler option would be useful for the "I want to comment something out to aid debugging" workflow.
This feature is a great way to waste people's time lol, what is the point? When you commit/ship code, ok no unused vars is nice, but when developing it? Horrible.
It's 2020 and I can't believe they still haven't fixed this (not even with a compiler flag). I did a project in Go about 5 years ago and overall liked the language but it was unusable for me solely because of this. The way I code I am constantly commenting/uncommenting stuff, so this "feature" in Go makes things take double the time for me... I've been checking back every few months since then to see if a sense of reason has overtaken the Go team, and so far no luck... Sucks. It's a great language otherwise and I'd love to use it more, but currently it's just not useable for me.
@RickO'Shea Assigning unused vars to a throwaway var _ is still a very cumbersome work around which demonstrably breaks developer flow. Every single time you comment something out you then need to go and stub all the declared but not used errors. Any team could implement standards and style checks as a commit hook or part of a CI/Gate job. The lack of agency given to developers here is patronizing and furthermore forces us to write worse code in order to be able to pull things apart. goimports solves the issue for imports, a compiler flag should be acceptable for variables.
A use case for unused variables is to have them show up in watches while debugging. I use this a lot and having to work around it with _ is really annoying.

F
Flimzy

That error is here to force you to write better code, and be sure to use everything you declare or import. It makes it easier to read code written by other people (you are always sure that all declared variables will be used), and avoid some possible dead code.

But, if you really want to skip this error, you can use the blank identifier (_) :

package main

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

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

becomes

package main

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

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

As said by kostix in the comments below, you can find the official position of the Go team in the FAQ:

The presence of an unused variable may indicate a bug, while unused imports just slow down compilation. Accumulate enough unused imports in your code tree and things can get very slow. For these reasons, Go allows neither.


Still, this is not so different from going commenting it out. And, I understand that this is for better code but would it be better if we can close a check why testing on our code and then open this check again after we want to finish the code and make it clean?
FWIW, I've had bad times reading code of others, but definitely not due to unused symbols. OTOH, I lost an hour today investigating methods to deal with this *#%$ golang "feature".
Sadly this answer is correct -- but that doesn't justify it. There's a world of difference between checking in code and simply executing it. When we check in code, we use linters to catch this kind of error. When we execute during rapid development, we don't have the same standards. It's unforgivable to confuse a compiler with a linter. Even the style police inside Google don't make that mistake.
thats a stupid decision from the Go's team. especially when trying to debug things.
Having the compiler treat this as an error is inexcusable. One can make the argument that this issue is the purview of linters and code style specs, but in the end the stupidity of making this a compile error comes up every time I'm doing some quick debugging and comment out a few lines of code. It's a sickening waste to have to go through the commented-out block and also comment out all of the declarations that were consumed there before I can compile. This turns a 2-second debugging habit into a slog that can burn 30x that long. The language spec has no business foisting this edict upon us.
M
Martin Tournoij

You can use a simple "null function" for this, for example:

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

Which you can use like so:

package main

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

    Use(a, b, c)
}

There's also a package for this so you don't have to define the Use function every time:

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

func main() {
  // [..]

  xulu.Use(a, b, c)
}

Is there a way to automatically use all declared vals instead? For development purposes this issue is really annoying =/
It seems the loop is unnecessary, see this answer below stackoverflow.com/a/62951339/722796
C
Community

According to the FAQ:

Some have asked for a compiler option to turn those checks off or at least reduce them to warnings. Such an option has not been added, though, because compiler options should not affect the semantics of the language and because the Go compiler does not report warnings, only errors that prevent compilation. There are two reasons for having no warnings. First, if it's worth complaining about, it's worth fixing in the code. (And if it's not worth fixing, it's not worth mentioning.) Second, having the compiler generate warnings encourages the implementation to warn about weak cases that can make compilation noisy, masking real errors that should be fixed.

I don't necessarily agree with this for various reasons not worth going into. It is what it is, and it's not likely to change in the near future.

For packages, there's the goimports tool which automatically adds missing packages and removes unused ones. For example:

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

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

You should be able to run this from any half-way decent editor − for example for Vim:

:!goimports -w %

The goimports page lists some commands for other editors, and you typically set it to be run automatically when you save the buffer to disk.

Note that goimports will also run gofmt.

As was already mentioned, for variables the easiest way is to (temporarily) assign them to _ :

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

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

_, _ = tasty, horrible

"the Go compiler does not report warnings, only errors that prevent compilation." Useful information, but terrible approach from language authors
Yeah, hard to agree. I'm testing out Go myself and am coming across these "errors" not because the code needs to be fixed, but because the code is not finished. If I want to comment something out during debugging...I need to rework other parts due to unused variables.
c
chuacw

I ran into this while I was learning Go 2 years ago, so I declared my own function.

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

And then you can use it like so:

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

The great thing about it is, you can pass anything into UNUSED.

Is it better than the following?

_, _, _ = x, y, z

That's up to you.


I find this method more useful than the blank identifier... As I'm developing in go, I like to run my code as early and as frequently as possible... It's more useful to me to make some variables "UNUSED" with my last line, than to comment out entire blocks that may not work as I expect.
This is a fantastic solution
Wonderfully concise, and easy to add that keyword to your linting system to ensure you "fix" it when it's actually necessary to do so.
m
max pleaner

In case others have a hard time making sense of this, I think it might help to explain it in very straightforward terms. If you have a variable that you don't use, for example a function for which you've commented out the invocation (a common use-case):

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

You can assign a useless/blank variable to the function so that it's no longer unused:

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

m
miltonb

One angle not so far mentioned is tool sets used for editing the code.

Using Visual Studio Code along with the Extension from lukehoban called Go will do some auto-magic for you. The Go extension automatically runs gofmt, golint etc, and removes and adds import entries. So at least that part is now automatic.

I will admit its not 100% of the solution to the question, but however useful enough.


m
maxime

I ran into this issue when I wanted to temporarily disable the sending of an email while working on another part of the code.

Commenting the use of the service triggered a lot of cascade errors, so instead of commenting I used a condition

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

P
Petrus Theron

As far as I can tell, these lines in the Go compiler look like the ones to comment out. You should be able to build your own toolchain that ignores these counterproductive warnings.


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

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now