-
Notifications
You must be signed in to change notification settings - Fork 17.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
flag: add TextVar to handle types that implement encoding.TextUnmarshaler #45754
Comments
Change https://golang.org/cl/313329 mentions this issue: |
This is clever. I've often found people reaching for third-party flag libraries just for the sake of having more types built-in and not having to implement This could also nudge more libraries towards implementing |
I could have used this today when adding a flag to control the logrus.Level of a service. |
/cc @robpike |
This proposal has been added to the active column of the proposals project |
Seems reasonable to me. Might be able to forestall some future requests. |
Based on the discussion above, this proposal seems like a likely accept. |
No change in consensus, so accepted. 🎉 |
flag.Var doesn't take a default value. Can't the TextUnmarshaller passed in be the default value, e.g. n := big.NewInt(3853882583591558728)
flag.TextVar(&n, "n", "Run integer factorization for this number") You could do an optional interface check for TextMarshaller, String, and then fallback to fmt.Sprint when printing the default. |
All the other functions that have There is a readability advantage to keeping the default value with the flag declaration when multiple flags are declared: var (
enable bool
period time.Duration
ipaddr net.IP
start time.Time
seed int64
email string
)
flag.BoolVar(&enable, "enable", true, "should we run this task?")
flag.DurationVar(&period, "period", time.Minute, "how often to refresh the task?")
flag.TextVar(&ipaddr, "ipaddr", net.IPv4(192, 168, 0, 1), "what server to connect to?")
flag.TextVar(&start, "start", time.Now(), "when should we start processing?")
flag.IntVar(&seed, "seed", 388342, "what seed to use for pseudo-randomization?")
flag.StringVar(&email, "email", "admin@domain.com", "what email should we send results to?") It would be reasonable if defaults were set first on the values before passing to var (
enable = true
period = time.Minute
ipaddr = net.IPv4(192, 168, 0, 1)
start = time.Now()
seed = int64(388342)
email = "admin@domain.com"
)
flag.BoolVar(&enable, "enable", "should we run this task?")
flag.DurationVar(&period, "period", "how often to refresh the task?")
flag.TextVar(&ipaddr, "ipaddr", "what server to connect to?")
flag.TextVar(&start, "start", "when should we start processing?")
flag.IntVar(&seed, "seed", "what seed to use for pseudo-randomization?")
flag.StringVar(&email, "email", "what email should we send results to?") However, that's not how the API works today. |
Makes sense. |
The
encoding.TextMarshaler
andencoding.TextUnmarshaler
interfaces are the de-facto way for a type to self-report that it can serialize to/from some humanly readable text format.The easiest ways to tie the
flag
package toencoding.TextUnmarshaler
is to:flag.Func
to declare an anonymous function that calls some unmarshal function under the hood. This approach takes >3 lines, but unfortunately does not display the default value in the usage documentation.flag.Value
and then useflag.Var
. This approach requires declaring 1 types and 2 methods and is generally more than 10 lines of cost.Both ways have detriments (either too long or drops default values being printed).
I propose adding:
along with the equivalent method on the
FlagSet
type.Example usage would be:
or
Of note, this is approach only requires a single line (other than the variable declaration) and works with any type that implements
encoding.TextMarshaler
andencoding.TextUnmarshaler
.There is a type safety loss where the
p
argument andvalue
argument may not be the same concrete type. Generics could resolve this problem.Within the standard library, there are 5 types that implement the interfaces:
"math/big".Float
"math/big".Int
"math/big".Rat
"net".IP
"time".Time
Each one could conceivably be useful to apply with the
flag
package.According to the latest version of all modules, there are ~14k types that implement
encoding.TextUnmarshaler
out of ~8.2M types total. While this only accounts 0.2% of all types, it's still a non-trivial number of implementations.The text was updated successfully, but these errors were encountered: