dongxi3859 2013-08-24 07:13
浏览 23
已采纳

golang类型转换无法按预期工作

I'm using go-flags to parse command line options.

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

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:

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:

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

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

  • 写回答

1条回答 默认 最新

  • dqcuq4138 2013-08-24 07:49
    关注

    An error is an interface with a single method Error() string. See http://golang.org/pkg/builtin/#error

    A flags.Error has such a method, so it can be used as an error.

    Conversely, however, a flags.Error is a struct, and there's no way to convert an arbitrary value to a struct.

    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. The syntax for that is e := err.(*flags.Error). This'll give you a value of type *flags.Error (or panic, if the underlying type isn't *flags.Error). You can avoid the panic in this case by using the comma-ok form, which is 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.
         }
      }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 BP神经网络控制倒立摆
  • ¥20 要这个数学建模编程的代码 并且能完整允许出来结果 完整的过程和数据的结果
  • ¥15 html5+css和javascript有人可以帮吗?图片要怎么插入代码里面啊
  • ¥30 Unity接入微信SDK 无法开启摄像头
  • ¥20 有偿 写代码 要用特定的软件anaconda 里的jvpyter 用python3写
  • ¥20 cad图纸,chx-3六轴码垛机器人
  • ¥15 移动摄像头专网需要解vlan
  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算