Golang flag library: Unable to override Usage function that prints out command line usage - go

I am working on a simple command line tool and I found the default Usage message a bit lacking. I want to define my own and I think I am doing it right I am referring to this example.
I commented out most of the code I had written so the file containing the main function now looks like this:
package main
import (
"flag"
"fmt"
"os"
)
func main() {
// set the custom Usage function
setupFlags(flag.CommandLine)
// define flags...
// then parse flags
flag.Parse()
// custom code that uses flag values...
}
func setupFlags(f *flag.FlagSet) {
f.Usage = func() {
fmt.Println("foo bar")
}
}
It seems like this should work, but it doesn't. When running <binary> -h I get the default usage message and not my custom foo bar message that I defined in my custom function. I am using Go version 1.3.3 on OSX. I found this commit but it is for Go 1.4rc2.
What am I doing wrong?

Edit:
Actually revisiting your code it works! What version of Go are you using? Maybe you need to rebuild your code.
The decision of what Usage function to call is in the flag.go source file, line 708, unexported function usage() (this is from Go 1.4):
func (f *FlagSet) usage() {
if f.Usage == nil {
if f == CommandLine {
Usage()
} else {
defaultUsage(f)
}
} else {
f.Usage()
}
}
This tells if the FlagSet.Usage is not nil, it will be called. If it is not called for you, it's most likely you're using a Go version prior to 1.4 (which you confirmed in your comment).
But since you're using the default flag.CommandLine flagset, you can simply write:
// Note "flag.Usage" instead of "f.Usage"
flag.Usage = func() {
fmt.Println("foo bar")
}

Related

GoDoc Example function for type/struct functions

Problem
I have written some example functions located in a *_test.go file to help clarify context for standalone public functions without issue. The problem on displaying comes when writing example functions for functions tied to a type.
Example
Here's a basic example of what I'm encountering.
Say we have a function in main.go like below:
type Client struct {
user string
ip string
}
func (c *Client) SendNotification(message string) error {
return nil
}
I want to create an example function for such in main_test.go, like below
func ExampleSendNotification() {
//Showoff code here
}
VSCode throws an error for that specific example, saying "ExampleSendNotification refers to unknown identifier: SendNotification". Also, it just does not appear as an example when running the godoc.
I've also tried this format:
func (c *Client) ExampleSendNotification() {
//Showoff code here
}
But then it just removes it as a test in VSCode, and doesn't appear
I found the answer just as I was finishing writing this. Thought I would still post for anybody else.
The trick is writing Example[Type]_[Method], so practically in my example, that would look like:
func ExampleClient_SendNotification() {
//Showoff code here
}

Go - Pass callback function to child (imported) package

I have a go program, MyPackage, and a logging package within this, MyPackage/logs. We have a function func Cleanup(params CleanupParams) written in MyPackage that we want to use as a callback in case of any panic within our log function implemented in MyPackage/logs. This function is already written and being used by MyPackage, so we could all the code across but this would be very messy and involve a lot of copying dependent functions.
The approach I am thinking is this: In MyPackage, we have a function func SetupLogs, and could pass this Cleanup callback function as a parameter. However this ends up being a circular dependency, just since we have reference to a function on MyPackage from our logs package. Is there a way to pass this function, maybe with type any?
package MyPackage
import . "MyPackage/logs"
func main() {
cleanupParams := ...
...
SetupLogs(Cleanup, cleanupParams)
...
}
func Cleanup(params *CleanupParams) {
...
}
And our logs package:
package MyPackage/logs
type LogCallback func(*CleanupParams)
func SetupLogs(callback LogCallback, cleanupParams *CleanupParams) {
...
go LogLoop(callback, cleanupParams)
}
func LogLoop(callback LogCallback, cleanupParams *CleanupParams) {
defer callback(cleanupParams)
for {
// Keep checking if we have been channelled another message to log
// If we are logging and have to Panic() then our callback gets run
}
}
So is there any way to call the parent function from the imported class, since we don't need to know anything about the types of the function or its parameters, we just need to push our program to make sure the method gets called?
Thank you!
Use type func() for the callback function:
func SetupLogs(callback func()) {
...
go LogLoop(callback)
}
func LogLoop(callback func()) {
defer callback()
for {
// Keep checking if we have been channelled another message to log
// If we are logging and have to Panic() then our callback gets run
}
}
Use a closure to create a func() that calls Cleanup with the parameters.
SetupLogs(func() { Cleanup(cleanupParams) })

how to generate or change code in compile time?

I want to add some code to start of function.
like
source code:
func A(){
do something...
}
final code:
func A(){
ADDED CODE
do something...
}
I`m using //go:generate right now,but it will change the source code and should run it every function changed,so I wonder if there any way to do the job in compile time
What about using a function call to add code?
package mypkg
var extra = func() {}
func A() {
extra()
// ...do something
}
Then you can include or exclude an extra file to the same package:
package mypkg
func init() {
extra = func() {
// ADDED CODE
}
}
You even could select from one ore more files with alternatives for the extra() function.
[H]ow to generate or change code in compile time?
You have to modify the compiler. (Don't do that.)

setting a variable from test file in golang

i'm trying to set a variable from my unit tests file
main_test.go
var testingMode bool = true
main.go
if testingMode == true {
//use test database
} else {
//use regular database
}
If I run "go test", this works fine. If I do "go build", golang complains that testingMode is not defined (which should be the case since tests aren't part of the program).
But it seems if I set the global variable in main.go, I'm unable to set it in main_test.
What's the correct way to about this?
Try this:
Define your variable as global in main.go:
var testingMode bool
And then set it to be true in your test file main_test.go:
func init() {
testingMode = true
}
Pierre Prinetti's Answer doesn't work in 2019.
Instead, do this. It's less then ideal, but gets the job done
//In the module that you are testing (not your test module:
func init() {
if len(os.Args) > 1 && os.Args[1][:5] == "-test" {
log.Println("testing")//special test setup goes goes here
return // ...or just skip the setup entirely
}
//...
}

How to access flags outside of main package?

We parse flags in main.go which is in main package, of course. Then we have another package where we want to read some flag's value.
flags.Args() work fine, it will return all non-flag values.
But I cannot figure out to how read already parsed value for a flag in a package other than main.
Is it possible?
Thanks
Amer
I had the same requirement recently and I wanted a solution that avoided calling flag.Parse repeatedly in init functions.
Perusing the flag package I found Lookup(name string) which returns a Flag which has a Value. Every built in Value implements the flag.Getter interface. The call chain looks like this:
flag.Lookup("httplog").Value.(flag.Getter).Get().(bool)
If you mistype the flag name or use the wrong type you get a runtime error. I wrapped the lookup in a function that I call directly where needed since the lookup and get methods are fast and the function is not called often. So the main package declares the flag.
// main.go
package main
import "flag"
var httplog = flag.Bool("httplog", false, "Log every HTTP request and response.")
func main() {
flag.Parse()
// ...
}
And the utility package, which is decoupled from main except for the flag name, reads the flag value.
// httpdiag.go
package utility
import "flag"
func logging() bool {
return flag.Lookup("httplog").Value.(flag.Getter).Get().(bool)
}
You can define the var storing the flag in the separate package, as an exported variable, then call the flag parsing in the main package to use that variable, like this:
mypackage/const.go
var (
MyExportedVar string
)
mainpackage/main.go
func init() {
flag.StringVar(&mypackage.MyExportedVar, "flagName", "defaultValue", "usage")
flag.Parse()
}
This way, everybody can access that flag, including that package itself.
Note:
this only works for exported variables.
You can define the flag in that package and call flag.Parse() in func init(), flag.Parse can be called multiple times.
However, if you want to access the flag's value from multiple packages you have to expose it or create an exposed function to check it.
for example:
// pkgA
var A = flag.Bool("a", false, "why a?")
func init() {
flag.Parse()
}
// main package
func main() {
flag.Parse()
if *pkgA.A {
// stuff
}
}
Also you can use FlagSet.Parse(os.Args) if you want to reparse the args.
When you parse your flags, parse them into global variables which start with an initial Capital so they are public, eg
package main
var Species = flag.String("species", "gopher", "the species we are studying")
func main() {
flag.Parse()
}
Then in your other package you can refer to them as
package other
import "/path/to/package/main"
func Whatever() {
fmt.Println(main.Species)
}

Resources