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

Ambiguous defer's behavior #38504

Closed
actopolus opened this issue Apr 17, 2020 · 3 comments
Closed

Ambiguous defer's behavior #38504

actopolus opened this issue Apr 17, 2020 · 3 comments

Comments

@actopolus
Copy link

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

$ go version go1.13.10 linux/amd64

Does this issue reproduce with the latest release?

Yes

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN="/go/bin"
GOCACHE="/.cache/go-build"
GOENV="/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/snap/go/5646"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/snap/go/5646/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
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-build798787028=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Run simple code: (https://play.golang.org/p/z2YsplDZOfp)

package main

import (
    "fmt"
)

func a() error {
  err := fmt.Errorf("Errorrrrrrooo")

  defer func() {
     err = nil
  }()

  return err
}

func b() (err error) {
  err = fmt.Errorf("Errorrrrrrooo")

  defer func() {
     err = nil
  }()

  return err
}

func main() {
  fmt.Println(a())
  fmt.Println(b())
}

What did you expect to see?

Errorrrrrrooo
Errorrrrrrooo

or

nil
nil

What did you see instead?

Errorrrrrrooo
nil
@urandom
Copy link

urandom commented Apr 17, 2020

There appears to be nothing ambiguous with the posted code.

@randall77
Copy link
Contributor

This is expected behavior.

In a:

  1. Assign non-nil error to a local variable
  2. Evaluate that local variable (to a non-nil error), set return value to it
  3. Run defer, set local variable to nil

That returns the non-nil error.

In b:

  1. Assign non-nil error to return variable
  2. Evaluate return variable (to a non-nil error), set return value to it
  3. Run defer, set return variable to nil (overwriting what was written in step 2)

That returns a nil error.

We generally discourage return x when there are named return variables. Set them using = and use a bare return.

@actopolus
Copy link
Author

Thank you for answers.
I'm sorry. I found it in old good post https://blog.golang.org/defer-panic-and-recover

@golang golang locked and limited conversation to collaborators Apr 17, 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