namsral/flag

Odd interaction with other libraries using flag behind the scenes

Opened this issue · 3 comments

Hi,

You may be interested in this ticket. There is an odd interaction when another library (in this case, the zero-downtime restart library endless) uses flags behind the scene to sneak in its own flags. A number of oddities crop up. To demonstrate, use this code. Compile the sample code to flagtest, and the demonstrations are below:

  • The using application's flags become illegal and generate an error if provided (./flagtest -param)
  • The library's flags become illegal and generate an error if provided (./flagtest -continue)
  • Which help message displayed differs depending on which flags are missed or provided (see the two examples above -- two different messages)

The behavior is the same whether the flag is defined globally, or in the scope of the main() function.

I do not know whether this is particular to fvbock/endless + namsral/flag, or if other flag-using libraries have the same problem with namsral/flag; I haven't investigated it yet. I thought you might like to be aware of the issue.

Hi,

Confirmed that it is not an issue with endless. Minimal test code:

main.go
testlib/testlib.go

Recommended directory structure:

   test/
      main.go
      testlib/
         testlib.go

Then in test:

  • go build -o test test.go
  • ./test -param (application flags are illegal)
  • ./test -libarg (library flags also illegal)

I'm certain this arises from the use of different flag libraries, but I am unable to recommend a fix at this time.

A library should not mandate the user interface of an application unless it is an UI library.

The flag package is a UI library, the testlib package in your example is not.

It is best practice to pass options in libraries through a public function. Take for example the database/sql package:

import "database/sql"

func main() {
    db, err := sql.Open("postgres", "user=pqgotest dbname=pqgotest sslmode=verify-full")
    …

Hi,

The code illustrates that the flag library hijacks the interpretation of flags globally, preventing it from being used with other (possibly UI, according to your terminology) libraries that access flags.

I can accept that this is a fundamental design flaw of the flags (both core and namsral versions) libraries, which access shared global state and interpret it as a rule set. It prevents composition of UI libraries for doing things like what endless attempts, which is attempting to re-fork the executable and pass in an argument indicating a restart rather than a virgin launch. Endless does not use namsral/flag for this; it uses the core library. The core library and namsral/flag can not both be used within the same application. It is as if using a Postgres SQL DB library implicitly prevented you from using a MySQL DB library because they both accessed some global shared state and read the configurations as being incompatible.

So: while I still see this as a fundamental design flaw, I don't disagree with closing the ticket as it isn't the namsral/flag's design flaw. It's just unfortunate that it inherits the flaw.