【问题标题】:How to create multi-level Error subtypes in Go如何在 Go 中创建多级错误子类型
【发布时间】:2019-06-13 21:30:25
【问题描述】:

我试图在 GO 中创建错误的子类型。 I've asked a question previously 关于此事。

现在我面临多种类型的问题。以下代码显示了错误类型定义:

/* Interfaces */
type UniversalError interface {
    CommonError1
}

type CommonError1 interface {
    error
    CommonError1()
}

/* Structs */
type Error1 struct {
    reason string
}

type Error2 struct {
    reason string
}

type Error3 struct {
    reason string
}

/* Interface function implementations */
func (error1 Error1) Error() string {
    return fmt.Sprintf(error1.reason)
}

func (error2 Error2) Error() string {
    return fmt.Sprintf(error2.reason)
}

func (error3 Error3) Error() string {
    return fmt.Sprintf(error3.reason)
}

func (Error1) CommonError1() {}
func (Error2) CommonError1() {}
func (Error3) UniversalError() {}

当我尝试运行以下代码时:

func main() {
    var err1 = Error1{reason: "Error reason 1"}
    var err2 = Error2{reason: "Error reason 2"}
    var err3 = Error3{reason: "Error reason 3"}

    fmt.Println("\n**** Types *****")
    printType(err1)
    printType(err2)
    printType(err3)
}

func printType(param error) {
    switch param.(type) {
    case UniversalError:
        switch param.(type) {
        case CommonError1:
            switch param.(type) {
            case Error1:
                fmt.Println("Error1 found")
            case Error2:
                fmt.Println("Error2 found")
            default:
                fmt.Println("CommonError1 found, but Does not belong to Error1 or Error2")
            }
        default:
            fmt.Println("Error3 Found")
        }
    default:
        fmt.Println("Error belongs to an unidentified type")
    }
}

printType() 函数打印以下内容:

**** Types *****
Error1 found
Error2 found
CommonError1 found, but Does not belong to Error1 or Error2

我需要将Error3 的类型标识为UniversalError,而不是CommonError1。我怎样才能做到这一点?我的方法有什么问题吗?

【问题讨论】:

  • 你不能。 Go 中没有“子类型”、没有父/子、没有类层次结构、没有继承,也没有超出接口的多态性。

标签: go types error-handling subtyping type-switch


【解决方案1】:

您使用了UniversalError() 方法,但您没有将其添加到接口“定义”中,所以这样做:

type UniversalError interface {
    CommonError1
    UniversalError()
}

您希望Error3 成为UniversalError。要使Error3 成为UniversalError,它必须实现其所有方法:UniversalError()CommonError1()。所以你必须添加这两种方法:

func (Error3) CommonError1()   {}
func (Error3) UniversalError() {}

通过这些更改,输出将是(在Go Playground 上尝试):

**** Types *****
Error belongs to an unidentified type
Error belongs to an unidentified type
CommonError1 found, but Does not belong to Error1 or Error2

提示:如果您想在编译时保证某个具体类型实现某个接口,请使用如下所示的空白变量声明:

var _ UniversalError = Error3{}

上述声明将值Error3 分配给UniversalError 类型的变量。如果Error3 不满足UniversalError,则会出现编译时错误。上述声明不会引入新变量,因为使用了blank identifier,这只是编译时检查。

如果您要删除Error3.CommonError1() 方法:

//func (Error3) CommonError1()   {}
func (Error3) UniversalError() {}

然后你会马上得到一个编译时错误:

./prog.go:49:5: cannot use Error3 literal (type Error3) as type UniversalError in assignment:
    Error3 does not implement UniversalError (missing CommonError1 method)

【讨论】:

  • 感谢您的回答。但是在这种情况下,为什么 Error1Error2 不被识别为 UniversalError 呢?这里我需要2个超级类型。 1.由Error1Error2组成->CommonError1 2.由CommonError1Error3组成->通用错误。
  • @ThisaruGuruge UniversalError 嵌入 CustomError1,而不是相反。如果你想要相反的关系,嵌入应该反映这一点。看起来你希望你的所有错误都是“普遍的”,所以CustomError1CustomError2 应该嵌入UniversalError。实现的方法必须按照那个。
  • 哦,我完全误解了。谢谢。
猜你喜欢
  • 2019-10-28
  • 2021-11-06
  • 1970-01-01
  • 2013-01-29
  • 2017-12-27
  • 2021-12-08
  • 2019-06-26
  • 2013-08-12
  • 1970-01-01
相关资源
最近更新 更多