如何在应用程序中丢弃在导入的第三方程序包中定义的标志

Consider, my application uses a third party library. I want my application to accept only the flags defined in my application and not the flags defined in imported packages.

package main

import (
    "flag"
    "fmt"
    log "github.com/golang/glog"
)

var myFlag int

func init() {
    flag.IntVar(&myFlag, "my_flag", 0, "need only my flags")
    confDir := "/Users/foo/test/logs" //assume this is read from configuration file
    flag.Set("log_dir", confDir)
    flag.Parse()
}

func main() {
    flag.Parse()
    log.Errorln("flag", myFlag)
    log.V(0).Infoln("flag", myFlag)
    fmt.Println("test", myFlag)
}

In above code sample, log package has many flags. After compiling when I execute following command, all flags including "my_flag" and flags from log package are displayed. But, I want to set the values for log package flags from my code with values obtained from configuration file.

  -alsologtostderr
        log to standard error as well as files
  -log_backtrace_at value
        when logging hits line file:N, emit a stack trace
  -log_dir string
        If non-empty, write log files in this directory
  -logtostderr
        log to standard error instead of files
  -my_flag int
        need only my flags
  -stderrthreshold value
        logs at or above this threshold go to stderr
  -v value
        log level for V logs
  -vmodule value
        comma-separated list of pattern=N settings for file-filtered logging

How to restrict my application executable from accepting other flags?

If you want to discard the flags of other packages, then you can use a new flagset instead of the default one.

package main

import (
    "flag"
    "fmt"
    "os"
)

var myFlag int

func main() {
    f := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
    f.IntVar(&myFlag, "my_flag", 0, "need only my flags")
    confDir := "/Users/foo/test/logs" //assume this is read from configuration file
    f.Set("log_dir", confDir)
    f.Parse(os.Args[1:])
    fmt.Println("test", myFlag)
}

flag functions that aren't methods use the exported package variable CommandLine. You could use

flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)

to reset the exported package variable CommandLine in flag. Here's a runnable example of that:

package main

import(
    "flag"
    "fmt"
    "os"
)

func main() {
    flag.Int("u", 1, "We don't want this flag")
    flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
    GoodInt := flag.Int("g", 100, "This is a flag we want!")
    flag.Parse()
    fmt.Println(*GoodInt)
}

Usage example:

$ go run program.go -h
Usage of /tmp/.../program:
  -g int
    This is a flag we want! (default 100)
exit status 2

If you prefer to avoid modifying the package variable, you can do so by creating a new FlagSet, which the answer that got in just before me demonstrates. In that case, make sure you call only methods on the new FlagSet, and avoid the flag functions that operate on CommandLine.