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

builtin/error: return value mismatch between "error interface" and custom error struct #54229

Closed
pomeh opened this issue Aug 3, 2022 · 3 comments

Comments

@pomeh
Copy link

pomeh commented Aug 3, 2022

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

1.19 (from online Go playground: https://go.dev/play/)

Does this issue reproduce with the latest release?

Yes (using "Go dev branch" from Go playground)

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

Unknown (Go Playground handle this for me)

What did you do?

I have a CustomError struct with an error:

type CustomError struct {
	error
	errcode string
}

I have 2 functions, one returning a builtin error (if any), and one other returning a CustomError (if any).

func A() error {
	return nil
}
func B() *CustomError {
	return nil
}

I call both function in a row, and store both error into the same variable of type error.

        // new variable "err"
	err := A()

        // reuse previous variable "err"
	err = B()

After each call, log err value, and log a custom message if any error is returned:

	err := A()
	fmt.Printf("a value is '%v'\n", err)
	if err == nil {
		fmt.Println("a is nil")
	} else {
		fmt.Println("a is not nil")
	}

	err = B()
	fmt.Printf("b value is '%v'\n", err)
	if err == nil {
		fmt.Println("b is nil")
	} else {
		fmt.Println("b is not nil")
	}

What did you expect to see?

Both function return nil, so we should have the following:

a value is '<nil>'
a is nil
b value is '<nil>'
b is nil

What did you see instead?

a value is '<nil>'
a is nil
b value is '<nil>'
b is not nil

It says b value is '<nil>', but the condition if err == nil is still evaluated to true.

Whole code to reproduce the issue is available below and in this Go playground example too:

package main

import "fmt"

type CustomError struct {
	error
	errcode string
}

func A() error {
	return nil
}
func B() *CustomError {
	return nil
}

func main() {
	err := A()
	fmt.Printf("a value is '%v'\n", err)
	if err == nil {
		fmt.Println("a is nil")
	} else {
		fmt.Println("a is not nil")
	}

	err = B()
	fmt.Printf("b value is '%v'\n", err)
	if err == nil {
		fmt.Println("b is nil")
	} else {
		fmt.Println("b is not nil")
	}
}

One interesting thing is when I change A function to return *CustomError too, instead of builtin error:

-func A() error {
+func A() *CustomError {
        return nil
 }

In this case, I get the expected behavior (everything is nil):

a value is '<nil>'
a is nil
b value is '<nil>'
b is nil

Here is the updated code for this working case, as long with the new Go Playground example:

package main

import "fmt"

type CustomError struct {
	error
	errcode string
}

func A() *CustomError {
	return nil
}
func B() *CustomError {
	return nil
}

func main() {
	err := A()
	fmt.Printf("a value is '%v'\n", err)
	if err == nil {
		fmt.Println("a is nil")
	} else {
		fmt.Println("a is not nil")
	}

	err = B()
	fmt.Printf("b value is '%v'\n", err)
	if err == nil {
		fmt.Println("b is nil")
	} else {
		fmt.Println("b is not nil")
	}
}
@seankhliao
Copy link
Member

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Aug 3, 2022
@seankhliao
Copy link
Member

Unlike many projects, the Go project does not use GitHub Issues for general discussion or asking questions. GitHub Issues are used for tracking bugs and proposals only.

For questions please refer to https://github.com/golang/go/wiki/Questions

@pomeh
Copy link
Author

pomeh commented Aug 3, 2022

Thanks for your quick and detailed answer.

I considered this a bug from an user/developer point of view, as this is an unexpected behavior, that's why I did not ask a question on other tools. I search on Github issue list but did not find anything either.

With your explanations, I now understand what's going on under the hood.

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

3 participants