Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two level if block changes a variable, and compiler says the variable is not used #36773

Closed
fmmajd opened this issue Jan 26, 2020 · 2 comments
Closed

Comments

@fmmajd
Copy link

fmmajd commented Jan 26, 2020

What version of Go are you using (go version)?

$ go version
go version go1.13.5 linux/amd64(docker)

Does this issue reproduce with the latest release?

it IS the lates release

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/app/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build118318990=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I'm using pgx package to work with postgres. but I copied needed code to reproduce the error without any dependencies

go play ground

as you see, logLevel var is changed in the conditional blocks base on whether there is an environment variable set for it. But the compiler gives an error: logLevel declared and not used

The error is addressing the inner inner block when an environment var is set, but can not be processed.

What did you expect to see?

I expected the code to be compiled without the error

What did you see instead?

the error

@zigo101
Copy link

zigo101 commented Jan 26, 2020

Both the inner logLevel and err variables are new declared variable.
The inner logLevel shadows the outer one.
This is a famous trap many new Gophers will encounter.

func main() {
	var logLevel LogLevel = LogLevelDebug
	logLevelStr, isSet := os.LookupEnv("POSTGRES_LOG_LEVEL")
	if isSet {
		// The logLevel is a new declared var
		logLevel, err := LogLevelFromString(logLevelStr)
		if err != nil {
			logLevel = LogLevelDebug
		}
	}
	config := Config{LogLev: logLevel}
	fmt.Println(config)
}

@ALTree
Copy link
Member

ALTree commented Jan 26, 2020

Hi,

the logLevel, err := LogLevelFromString(logLevelStr) line declares a brand-new logLevel which scope is limited to the if isSet { block. This is because := (that you are using because you need a new err) will always create new variables when used in the multiple assignment form a, b, c ... := .

Basically the logLevel, err := LogLevelFromString(logLevelStr) line is not setting the var logLevel that you declared at line 10, it's creating a new one. That one is not used. So the compiler error is correct.

To fix this, you can pre-declare err and then write

logLevel, err = LogLevelFromString(logLevelStr)

Also see #377.

Closing here, since this is not a bug.

@ALTree ALTree closed this as completed Jan 26, 2020
@golang golang locked and limited conversation to collaborators Jan 25, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants