-
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
proposal: flag: Add IgnoreOnError ErrorHandling #58839
Comments
CC @robpike |
The flag package serves well for the uses it's intended for. Given the depth of analysis you have done, I think what you're really looking for is a more capable replacement. I would prefer we don't add more (and more confusing) features to the existing interface. Also, given the way flags are interpreted, I do not believe it is possible in general to ignore unknown flags, which is a strong argument against adding this feature. |
I don't think it's possible to ignore unknown flags either, an argument passed to a flag can start with a
If |
How about adding an extra callback instead of extending the enum? A callback would get the tail of unprocessed args and returns an IMHO this would give users freedom of handling arguments, at the same time not bloating Such user callback might look like this: integration := func(args []string) uint {
switch args[0] {
case "-serviceAparam", "-oddWindowsFlag":
return 1
case "-serviceBparam":
if len(args) > 1 && args[1] == "--foobar" {
return 2
}
return 1
default:
return 0
}
}
Flag.ErrorHandlingFunc = integeration |
It still seems to me that a richer, externally provided flags package is what you're after. The one in the standard library is deliberately minimalist. |
Personally, I'm fine with |
@seankhliao I tested the case where a In your first example: Second example: Both use the same approach of skipping until the next space, and both should parse |
@WojciechMula Thanks for considering this issue. Your solution solved the problem, but I'm looking for a minimalistic solution which matches the style of |
This proposal has been added to the active column of the proposals project |
As people have noticed, this is infeasible because you don't know whether an unrecognized flag takes arguments or not. Plenty of flags take flag-like arguments, like -ldflags=-w in the go build command, which could be written |
Based on the discussion above, this proposal seems like a likely decline. |
Thanks @rsc for taking a look at this proposal. I recently discovered that pflag implements this feature already. (code) Likely they have the same issues as described in @rsc 's earlier comment. However, their solution works for me because I, as the binary author, can guarantee that there are no sub commands when parsing args. I think if you can guarantee that the command is a leaf node in the command tree, then it's safe to ignore unknown flags with the algorithm I originally posted.
@robpike 's earlier comment rings true: golang users who are interested in this functionality are best suited to use a richer flag parser than the deliberately minimalist one. |
This proposal has been declined as retracted. |
Related Issue: #15352
Go's flag package does not support parsing flags when undefined flags exist.
Go's flag.FlagSet struct has ErrorHandling support with three values:
ContinueOnError
,ExitOnError
, andPanicOnError
.ExitOnError
andPanicOnError
are straightforward, butContinueOnError
stops processing arguments if an error is encountered.There should be a fourth option to silently ignore undefined flags and keep parsing.
What would this be called?
Potential names for a new
ErrorHandling
constant could be:OmitOnError
(omit the bad flag and keep parsing)KeepParsingOnError
(omit the bad flag and keep parsing)Why do users need this ability?
Integration point between two services. Suppose there are two processes/services: caller A and callee B, where B is a go binary. These two services could change over time, meaning that invocations of B could fail due to arg parsing. Suppose there are multiple versions of B but one version of A. A would need to know the exact sets of flags to pass into B1 and B2.
A similar case is how JSON parsers have the option to ignore unknown fields. This is the same problem, solved for REST microservices which use JSON as the interface for passing information between two services.
Deploying Kubernetes applications is another use case. I might want my service to resiliently accept flags to ensure my Pod runs successfully.
What alternatives do users have?
ErrorHandling
to a value which meets their needs instead.ContinueOnError
and ensure that unknown fields are always at the end of the argument list. If the user could ensure this, then usingContinueOnError
is sufficient. However, keeping this invariant true would be very challenging and most likely not worth the effort if not impossible.How would this be implemented?
Flag parsing must remain consistent for all cases. However, there's one case which makes the implementation difficult: undefined boolean flags. This is highlighted in the earlier proposal, #6112 (comment)
When parsing an unknown flag, the unknown flag's argument should be skipped in order to correctly parse the rest of the defined flags. The loop must keep the invariant that no part of a defined flag was skipped.
This would require looking ahead to the next argument to see if it's a value (doesn't start hyphen) or a flag (starts with hyphen). It would also require understanding the
=
separator, even for undefined flags.I haven't tested extensive, but here are some examples:
./main -a=2 -b 3 -undefined-bool-flag
./main -a=2 -undefined-bool-flag -b
./main -a=2 -undefined-int-flag 5 -b 3
./main -undefined-bool-flag1 -undefined-bool-flag2
It's impossible to know the intended type of the undefined flag, but I don't think that means it's impossible to parse the command line arguments. These examples show the intended type of the flags, but the solution to parse them, look ahead and conditionally skip by 1 or 2, is the same regardless.
I haven't thought about more complicated flags, such as repeated flags (
-some a -some b -> [a, b]
or-some a b -> [a, b]
, other than to quickly say the look ahead could proceed until an argument started with a hyphen and skip up to that point.The text was updated successfully, but these errors were encountered: