Extends a Error struct, but encounter Type '*MyError' has both field and method named 'Error'

Issue

I come from java.

And I am using a framework that already define an Error in errs package, I want to extend it so that I can add more fields to it. So I try using inheritance of go.

// Error to inherit from errs.Error
type MyError struct {
    errs.Error
    ErrDetail string    //more message to my error
    st        []uintptr 
}

// override Error() so that the message can be more specific
func (e *MyError) Error() string {
    if e == nil {
        return ErrorCodeSuccess.ErrDetail
    }
    return fmt.Sprintf("Code:%d, ErrDetail:%s, Msg:%s", e.GetCode(), e.GetErrDetail(), e.GetMsg())
} 

This is very straightforward for a java programmer. But I get

 Type '*MyError' has both field and method named 'Error'.

This is very frustrating since the method Error is define in built-in package, and the name Error is define in my framework, is there any workaround to solve this problem´╝č

Solution

You can use a type alias:

type SDKErr = errs.Error

// Error to inherit from errs.Error
type MyError struct {
    SDKErr
    ErrDetail string    //more message to my error
    st        []uintptr 
}

func (e *MyError) Error() string {
    // ...
} 

Now the name of the embedded field is SDKErr, but it won’t conflict with the method name, and it can be used wherever errs.Error is expected without the need to convert.

Playground: https://go.dev/play/p/XSWi5hzHGPh

Of course you could also use a named field, instead of an alias:

type MyError struct {
    SDKErr errs.Error
    ErrDetail string    //more message to my error
    st        []uintptr 
}

And then call the methods of errs.Error simply like e.SDKErr.GetCode(). However if MyError is meant, for example, to be serialized to JSON, the fields of errs.Error would appear as a nested object, whereas with the type alias they would be "flattened".

Basically if errs.Error were defined as:

type Error struct {
    Code int
}

With the type alias and embedded field, JSON would look like:

{"Code":0,"ErrDetail":""}

vs named field:

{"SDKErr":{"Code":0},"ErrDetail":""}

Answered By – blackgreen

Answer Checked By – Candace Johnson (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.