alexflint / go-arg

Struct-based argument parsing in Go
BSD 2-Clause "Simplified" License
1.9k stars 98 forks source link

Inline structs are not supported #242

Open infogulch opened 3 months ago

infogulch commented 3 months ago

I'm using inline embedded structs to add structure to my config for json encoding without having to explicitly name a bunch of sub-structs, but go-arg doesn't like it:

var args struct {
    A struct {
        B string
        C string
    }
    D string
}
arg.MustParse(&args)
$ go run . -h
.A: struct { B string; C string } fields are not supported
exit status 255

I see that the docs say it supports embedded structs, but it doesn't mention inline embedded struct (my name, perhaps there's a more formal name). Is this intentionally unsupported, or is it more of an oversight / "didn't think of doing it like that before"? Would you consider adding support for these types of struct definitions?

alexflint commented 3 months ago

If you do it like this then it should work as expected:

type T struct {
    B string
    C string
}

var args struct {
    T
    D string
}

Technically the setup you have in your original example is inline but not embedded. Embedded is when a field has a type but no name. In your example, the field does actually have the name "A". Go-arg does support embedded structs, but it doesn't do anything special for inline structs. As a result, what you have in your original example is equivalent from go-arg's perspective to:

var args struct {
    A SomeType
    D string
}

The reason that go-arg is complaining is that it doesn't know how to process command line arguments into your SomeType here.

infogulch commented 3 months ago

Yes that is correct, my example uses inline structs not embedded structs.

The reason that go-arg is complaining is that it doesn't know how to process command line arguments into your SomeType here.

So I guess this is a feature request: I think it would be nice if go-arg supported inline structs.

alexflint commented 1 month ago

@infogulch But how would the library behave in the case that you outlined above?

One of the issues is that from a reflection point of view, there isn't much difference between inline and non-inline structs, i.e. these two show up as more or less the same thing from reflection:

type inner struct {
   ...
}

type args struct {
  x inner
}

and

type args struct {
  x struct { ... }
}

Given that these two cases would be handled in the same way, what behavior would be most appropriate?

infogulch commented 1 month ago

It would be fine if it worked the same in both cases I think. I.e. make inline structs work the same as named structs.