提问人:tte 提问时间:11/17/2023 更新时间:11/18/2023 访问量:45
从构造函数返回自定义错误类型的惯用方法是什么?[关闭]
What is idiomatic way to return custom error type from constructor? [closed]
问:
据我所知,在golang源代码中,除了包本身之外,没有错误构造函数的示例。基本上,作者返回手动构造的类型。errors
例如,我们有带有自定义错误结构的包net
OpError
type OpError struct {
// Op is the operation which caused the error, such as
// "read" or "write".
Op string
...
}
func (e *OpError) Error() string {
...
}
他们通过直接声明来使用它们,没有任何构造函数
func (c *conn) SetDeadline(t time.Time) error {
if !c.ok() {
return syscall.EINVAL
}
if err := c.fd.SetDeadline(t); err != nil {
return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
}
return nil
}
func (c *conn) File() (f *os.File, err error) {
f, err = c.fd.dup()
if err != nil {
err = &OpError{Op: "file", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
}
return
}
我想知道,根据我应该返回的类型编写自定义错误构造函数的惯用方法是什么?我应该返回内置接口错误还是我的自定义类型的实例?
也许有我们的自定义域错误类型,其中包含一些域代码和抽象详细信息
type DomainErrorCode int
type DomainError struct {
err error
Code DomainErrorCode
Details []byte
}
func (e *DomainError) Error() string {
return e.err.Error()
}
构造函数可以是
// A
func NewDomainError(err error, code DomainErrorCode, details Details) error {
return &DomainError{err: err, Code: code, Details: details}
}
// B
func NewDomainError(err error, code DomainErrorCode, details Details) *DomainError {
return &DomainError{err: err, Code: code, Details: details}
}
选项非常灵活,允许您构造自定义错误和到达属性,如 或 。
Option 更加封装,如果您需要访问自定义属性,则需要某种断言。B
Code
Details
A
然后我看到了 Generality 的官方指南
如果某个类型仅用于实现接口,并且永远不会有超出该接口的导出方法,则无需导出类型本身。仅导出接口可以清楚地表明,除了接口中描述的内容之外,该值没有其他有趣的行为。它还避免了在通用方法的每个实例上重复文档的需要。
那么在这个例子中编写构造函数的惯用方法是什么?似乎是选项,因为除了内置之外,我没有任何方法。但这限制了对重要自定义属性的访问,并且如果需要字段,则类型断言将花费额外的精力。对我来说,选择似乎更合理A
interface error
B
答:
1赞
Burak Serdar
11/17/2023
#1
不要返回键入的错误。总是返回.这有几个原因。其中两个是:error
- 返回的错误可能包装到其他错误类型中,也可能包装其他错误类型。因此,在堆栈的较高位置,您应该处理 ,并将其转换为您期望使用包中的工具的具体错误类型。这样,您可以处理已知的错误,并检测您不知道的错误。
error
errors
- 更重要的是,如果使用具体类型定义错误变量,则从该变量派生的接口永远不会为 nil,即使具体类型本身为 nil。那是:
error
func f() *MyError {return nil}
var err error
err=f()
if err==nil { // This is never nil
...
}
这是因为接口同时包含类型和值,如果类型为非 nil,则接口值本身不能为 nil,即使值为 nil。
0赞
Phelipe Wener
11/18/2023
#2
Golang 建议直接使用错误类型。例如,除非您想将其用作 API 的结果。
var (
ErrFatalViolation = errors.New("fatal violation")
)
所以你可以退回它:
return errors.Join(
ports.ErrFatalViolation,
errors.New("id is nil"),
)
并像这样使用它:
if errors.Is(err, ports.ErrFatalViolation)
评论
error