如何将面向用户的错误与Golang中的内部错误完全分开?

时间:2016-07-13 21:22:28

标签: go

我遇到了一个常见的模式,我有一个接受用户输入的函数,并返回一个成功的输出值或一个错误。但它可以返回不同类型的错误,其中一些是用户输入错误的结果,另一些是内部错误导致的结果(例如,DB不可用)。

我的功能有如下签名:

// ProcessInput takes a user-input string and returns a processed value
func ProcessInput(input string) (ProcessedValue, error, error) {}

如果没有遇到错误,第一个返回值是有意义的(不是nil),如果用户输入验证失败,则第二个返回值是错误,如果发生意外的内部错误,则第三个返回值是错误。

这样可以正常工作,但感觉不是很干净,从签名看不同的错误是不明显的。我考虑过命名错误返回,但我不喜欢命名返回参数的副作用。

我可以应用更清洁的其他模式吗?我是否应该有一个错误返回并按呼叫者方面的类型区分?

2 个答案:

答案 0 :(得分:8)

返回多个error对我来说似乎不太像。

为什么没有名为UserError的接口定义一个返回适合显示用户的消息的方法。如果返回的错误未实现UserError,则显示标准的“内部服务器错误”消息。例如:

type UserError interface {
    error
    UserError() string
}

type emptyInput struct {}

func (e emptyInput) Error() string {
    return e.UserError()
}    

func (emptyInput) UserError() string {
    return "Empty input"
}

func ProcessInput(input string) (*ProcessedValue, error) {
    if input == "" {
        return nil, &emptyInput{}
    }
}

func httpHandler() {
    val, err := ProcessInput(input)
    if err != nil {
        if userErr := err.(UserError); userErr != nil {
            // show userError.UserError() to user
        } else {
            // Log error
            // show Internal server error message
        }
    }
}

答案 1 :(得分:1)

  

我是否应该返回一个错误并按类型区分   来电方?

这就是我的建议。您可以为不同类型的错误创建全局错误变量。调用者可以检查返回的错误类型。

var ErrValidation = fmt.Errorf("Validation failed.")

func ProcessInput(input string) (ProcessedValue, error) {
    if !validate(input) {
        return nil, ErrValidation
    }
    // process stuff and return
}

在来电方面:

value, err := ProcessInput(input)
if err != nil {
    if err == ErrValidation {
        // Tell user validation failed
    } else {
        // Show internal server error message
    }
}
// do things with value