golang类型转换不起作用(I)预期

时间:2013-08-24 07:13:02

标签: types go flags

我正在使用go-flags来解析命令行选项。

根据go-flags docs:“... [if]在命令行参数中指定-h或--help,将自动打印一条帮助消息。此外,特殊错误类型ErrHelp返回。“

我打电话的方法是:

func (p *Parser) Parse() ([]string, error) {

我打电话给:

var opts struct {
    // ...
}

func main() {

    parser := flags.NewParser(&opts, flags.Default)

    args, err := parser.Parse()

定义ErrHelp的文件的片段如下所示:

type ErrorType uint

const (
    // Unknown or generic error
    ErrUnknown ErrorType = iota

    // Expected an argument but got none
    ErrExpectedArgument

    // ...

    // The error contains the builtin help message
    ErrHelp

    // ...
)

// Error represents a parser error. The error returned from Parse is of this
// type. The error contains both a Type and Message.
type Error struct {
    // The type of error
    Type ErrorType

    // The error message
    Message string
}

// Get the errors error message.
func (e *Error) Error() string {
    return e.Message
}

func newError(tp ErrorType, message string) *Error {
    return &Error{
        Type:    tp,
        Message: message,
    }
}

所以他们有这种自定义的“错误”类型。在上面的Parse()方法中,在内部,错误是通过如下代码块创建的:

    help.ShowHelp = func() error {
        var b bytes.Buffer
        p.WriteHelp(&b)
        return newError(ErrHelp, b.String())
    }

正如您所看到的,newError()返回“* Error”作为其类型。但是上面的匿名函数返回类型“错误” - 所以这些类型必须兼容。(?)

但现在回到原来的问题 - 我只是想看看我的“错误”是否是“错误”并且成员“类型”等于ErrHelp。所以我试试这个:

if err != nil && flags.Error(err).Type == flags.ErrHelp {

或者就是这样:

fmt.Printf("test:", flags.Error(err))

编译器给我的任何一种方式:

  

main.go:37:无法将err(类型错误)转换为flags.Error

但是没有说明为什么不能进行转换。有什么想法吗?

(我不知道“* Error”如何在上面的匿名函数中成功转换为“error”,而且我更不明白为什么如果有效,那么我无法将其转换回另一种方式。 ..我必须在这里丢失一些非常愚蠢的东西,但我不知道它是什么。)

1 个答案:

答案 0 :(得分:9)

error是具有单个方法Error() string的接口。见http://golang.org/pkg/builtin/#error

flags.Error有这样的方法,因此可以用作error

然而,相反,flags.Error是一个结构,并且无法将任意值转换为结构。

可以做的是,我认为这是你问题的答案,如果你在flags.Value内有error,那么你可以将error强制转换回基础类型。其语法为e := err.(*flags.Error)。这将为您提供类型*flags.Error的值(如果基础类型不是*flags.Error,则为恐慌)。在这种情况下,您可以使用逗号表格e, ok := err.(*flags.Error)来避免恐慌。

具体地说,你会写:

  args, err := flags.Parse()
  if err != nil {
     if ferr, ok := err.(*flags.Error); ok {
       // ... something using ferr
     } else {
       // ... deal with non-flags.Error case, if that's possible.
     }
  }