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.)
Type conversion happens when we assign the value of one data type to another. Statically typed languages like C/C++, Java, provide the support for Implicit Type Conversion but Golang is different, as it doesn't support the Automatic Type Conversion or Implicit Type Conversion even if the data types are compatible.
You can convert numbers to strings by using the strconv. Itoa method from the strconv package in the Go standard libary. If you pass either a number or a variable into the parentheses of the method, that numeric value will be converted into a string value.
In order to convert an integer value to string in Golang we can use the FormatInt function from the strconv package. FormatInt returns the string representation of i in the given base, for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z' for digit values >= 10.
An integer can be converted to a string in Golang using the Itoa function within the strconv library.
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.
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With