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

huangapple go评论103阅读模式
英文:

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

问题

我来自Java。

我正在使用一个已经在errs包中定义了Error的框架,我想扩展它以便可以添加更多的字段。所以我尝试使用Go的继承。

// 继承errs.Error的Error类型
type MyError struct {
	errs.Error
	ErrDetail string    //我的错误的更多信息
	st        []uintptr 
}

// 重写Error()方法以便消息可以更具体
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())
} 

对于Java程序员来说,这非常直观。但是我得到了以下错误:

 类型 '*MyError' 同时具有字段和方法名 'Error'。

这非常令人沮丧,因为Error方法是在内置包中定义的,而Error名称是在我的框架中定义的。有没有解决这个问题的方法?

英文:

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?

答案1

得分: 2

你可以使用类型别名(type alias)来实现:

type SDKErr = errs.Error

// Error 继承自 errs.Error
type MyError struct {
    SDKErr
    ErrDetail string    // 更多错误信息
    st        []uintptr 
}

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

现在嵌入字段的名称是 SDKErr,但它不会与方法名冲突,并且可以在任何需要 errs.Error 的地方使用,无需进行转换。

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

当然,你也可以使用命名字段,而不是类型别名:

type MyError struct {
    SDKErr errs.Error
    ErrDetail string    // 更多错误信息
    st        []uintptr 
}

然后可以简单地像 e.SDKErr.GetCode() 这样调用 errs.Error 的方法。然而,如果 MyError 用于序列化为 JSON,errs.Error 的字段将出现为嵌套对象,而使用类型别名时它们将被“展平”。

基本上,如果 errs.Error 定义为:

type Error struct {
    Code int
}

使用类型别名和嵌入字段,JSON 将如下所示:

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

而使用命名字段则如下所示:

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

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":""}

huangapple
  • 本文由 发表于 2022年3月21日 17:30:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/71555368.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定