【问题标题】:Returning Interface in GolangGolang 中的返回接口
【发布时间】:2019-04-26 15:13:55
【问题描述】:

假设我们想在error 接口上扩展Error() 函数。我们可以简单地创建一个从实现Error() 方法的字符串派生的结构。例如:

type NewUser struct {
    Email           string
    Password        string
}
type ErrMissingField string

func (e ErrMissingField) Error() string {
    return string(e) + " is required"
}

func (u *NewUser) OK() error {
    if len(u.Email) == 0 {
        return ErrMissingField("email")
    }
    if len(u.Password) == 0 {
        return ErrMissingField("password")
    }
    return nil
}

以上代码将返回email is requiredpassword is required

但是,如果我创建自己的界面,比如说ResponseError,就像这样:

type ResponseError interface {
    ErrorMsg() string
}

type CustomErr string

func (c CustomErr) ErrorMsg() string {
    return "[Error] " + string(c)
}
func (u *NewUser) NewOK() ResponseError {
    if len(u.Email) == 0 {
        return CustomErr("Email required!")
    }
    if len(u.Password) == 0 {
        return CustomErr("Password Required!")
    }
    return nil
}

它不会打印我用[Error] 编写的方法实现。它只是打印我传递给结构Email required!Password Required! 的字符串。

如何解决这个问题?

【问题讨论】:

  • 您用来打印的代码在哪里?
  • 你的目标是什么?我不明白你想要完成什么。
  • 我使用 fmt 来打印错误信息。我的目标只是自定义错误界面。顺便说一句,nighfury 已经涵盖了答案

标签: go methods interface


【解决方案1】:

如果你使用 fmt 打印,那么来自https://golang.org/pkg/fmt

  1. 如果操作数实现了错误接口,则会调用Error方法将对象转换为字符串,然后根据动词的要求(如果有)进行格式化。

  2. 如果操作数实现方法 String() 字符串,将调用该方法将对象转换为字符串,然后根据动词(如果有)的要求对其进行格式化

这就是为什么当你实现 Error 接口时,它通过调用Error() 函数来打印。如果您想为其他接口(如ResponseError)自定义输出,请实现String() 方法。

package main

import (
    "fmt"
)

type NewUser struct {
    Email           string
    Password        string
}

type ResponseError interface {
    ErrMsg()
    String() string
}

type CustomErr string

func (c CustomErr) String() string {
    return "[Error] " + string(c)
}

func (c CustomErr) ErrMsg() {}

func (u *NewUser) NewOK() ResponseError {
    if len(u.Email) == 0 {
        return CustomErr("Email required!")
    }
    if len(u.Password) == 0 {
        return CustomErr("Password Required!")
    }
    return nil
}

func main() {
    u := &NewUser{}
    fmt.Println(u.NewOK())
}

去游乐场:https://play.golang.org/p/khAAtLodEND

【讨论】:

    【解决方案2】:

    Go 在打印时以不同的方式对待实现 errortypes。您的接口ResponseError 确实通过添加Error() string 实现error

    要可视化我在说什么,请参阅以下使用error 接口的示例:

    type NewUser struct {
        Email    string
        Password string
    }
    
    type ResponseError interface {
        error
        ErrorMsg() string
    }
    
    type CustomErr string
    
    func (c CustomErr) ErrorMsg() string {
        return "[Error] " + string(c)
    }
    
    func (c CustomErr) Error() string {
        return c.ErrorMsg()
    }
    
    func (u *NewUser) NewOK() ResponseError {
        if len(u.Email) == 0 {
            return CustomErr("Email required!")
        }
        if len(u.Password) == 0 {
            return CustomErr("Password Required!")
        }
        return nil
    }
    
    func main() {
        user := NewUser{}
        fmt.Printf("Using %%s: %s\n", user.NewOK())
        fmt.Printf("Using %%v: %v\n", user.NewOK())
        fmt.Printf("Using %%v and call function ErrorMsg: %v\n", user.NewOK().ErrorMsg())
        fmt.Printf("Using %%s and call function ErrorMsg: %s\n", user.NewOK().ErrorMsg())
    }
    

    这将打印以下内容:

    Using %s: [Error] Email required!
    Using %v: [Error] Email required!
    Using %v and call function ErrorMsg: [Error] Email required!
    Using %s and call function ErrorMsg: [Error] Email required!
    

    但是没有error接口:

    type NewUser struct {
        Email    string
        Password string
    }
    
    type ResponseError interface {
        ErrorMsg() string
    }
    
    type CustomErr string
    
    func (c CustomErr) ErrorMsg() string {
        return "[Error] " + string(c)
    }
    
    
    func (u *NewUser) NewOK() ResponseError {
        if len(u.Email) == 0 {
            return CustomErr("Email required!")
        }
        if len(u.Password) == 0 {
            return CustomErr("Password Required!")
        }
        return nil
    }
    
    func main() {
        user := NewUser{}
        fmt.Printf("Using %%s: %s\n", user.NewOK())
        fmt.Printf("Using %%v: %v\n", user.NewOK())
        fmt.Printf("Using %%v and call function ErrorMsg: %v\n", user.NewOK().ErrorMsg())
        fmt.Printf("Using %%s and call function ErrorMsg: %s\n", user.NewOK().ErrorMsg())
    }
    

    输出是:

    Using %s: Email required!
    Using %v: Email required!
    Using %v and call function ErrorMsg: [Error] Email required!
    Using %s and call function ErrorMsg: [Error] Email required!
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-22
      • 2016-11-30
      • 2012-08-08
      • 1970-01-01
      • 2020-05-15
      • 1970-01-01
      • 2018-07-29
      • 2019-03-20
      相关资源
      最近更新 更多