简体   繁体   English

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

[英]golang type conversion not working as (I) expected

I'm using go-flags to parse command line options. 我正在使用go-flags来解析命令行选项。

Per the go-flags docs: "... [if] either -h or --help was specified in the command line arguments, a help message will be automatically printed. Furthermore, the special error type ErrHelp is returned." 根据go-flags文档: “... [if] -h或--help在命令行参数中指定,将自动打印一条帮助消息。此外,返回特殊错误类型ErrHelp。”

The method I'm calling is: 我打电话的方法是:

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

I'm calling it with: 我打电话给:

var opts struct {
    // ...
}

func main() {

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

    args, err := parser.Parse()

A snippet from the file that defines ErrHelp looks like this: 定义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,
    }
}

So they have this custom "Error" type. 所以他们有这种自定义的“错误”类型。 And in the Parse() method above, internally, the error is getting created with a block of code like this: 在上面的Parse()方法中,在内部,错误是通过如下代码块创建的:

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

As you can see newError() returns "*Error" as it's type. 正如您所看到的,newError()返回“* Error”作为其类型。 But the anonymous function just above returns type "error" - so those types must be compatible.(?) 但上面的匿名函数返回类型“错误” - 所以这些类型必须兼容。(?)

But now back to the original problem - I'm just trying to see if my "err" is an "Error" and has member "Type" equal to ErrHelp. 但现在回到原来的问题 - 我只是想看看我的“错误”是否是“错误”并且成员“类型”等于ErrHelp。 So I try this: 所以我试试这个:

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

Or even just this: 或者就是这样:

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

And either way the compiler gives me: 无论哪种方式编译器给我:

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

But does not state why that conversion can't be done. 但是没有说明为什么不能进行转换。 Any ideas? 有任何想法吗?

(I don't get how "*Error" successfully converts to "error" in the anonymous function above, and I even more don't get why if that works then I can't convert it back the other way... I must be missing something really dumb here, but I'm not seeing what it is.) (我不知道“* Error”如何在上面的匿名函数中成功转换为“错误”,我甚至更不明白为什么如果有效,那么我无法将其转换回来...我我必须遗漏一些真正愚蠢的东西,但我不知道它是什么。)

An error is an interface with a single method Error() string . error是具有单个方法Error() string的接口。 See http://golang.org/pkg/builtin/#error 请参阅http://golang.org/pkg/builtin/#error

A flags.Error has such a method, so it can be used as an error . flags.Error有这样的方法,所以它可以用作error

Conversely, however, a flags.Error is a struct, and there's no way to convert an arbitrary value to a struct. 但是,相反, flags.Error是一个结构,并且无法将任意值转换为结构。

What you can do is, and I think this is the answer to your question, is that if you've got a flags.Value inside an error , then you can cast the error back to the underlying type. 可以做的是,我认为这是你的问题的答案,如果你有一个flags.Value error内的值,那么你可以将error转回基础类型。 The syntax for that is e := err.(*flags.Error) . 其语法是e := err.(*flags.Error) This'll give you a value of type *flags.Error (or panic, if the underlying type isn't *flags.Error ). 这将为您提供类型*flags.Error的值(如果底层类型不是*flags.Error )。 You can avoid the panic in this case by using the comma-ok form, which is e, ok := err.(*flags.Error) . 在这种情况下,您可以使用逗号表单来避免恐慌,即: e, ok := err.(*flags.Error)

Concretely, you would write: 具体来说,你会写:

  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.
     }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM