Skip to content
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: global Usage func disregards FlagSet.SetOutput #20998

Closed
vearutop opened this issue Jul 13, 2017 · 2 comments
Closed

flag: global Usage func disregards FlagSet.SetOutput #20998

vearutop opened this issue Jul 13, 2017 · 2 comments
Labels
Documentation FrozenDueToAge NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Milestone

Comments

@vearutop
Copy link
Contributor

What version of Go are you using (go version)?

go version go1.8.2 darwin/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/vpoturaev/golang"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.8.2/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.8.2/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/p5/fnl90gfx5_5f9599s3hpthfw0000gq/T/go-build760766867=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

What did you do?

package main

import (
	"flag"
	"io/ioutil"
	"os"
)

func main() {
	var i int
	flag.IntVar(&i, "i", 2, "sample int")
	flag.CommandLine.SetOutput(ioutil.Discard)
	os.Args = []string{"app", "-i=1", "-unknown"}
	flag.Parse()
}

https://play.golang.org/p/05pwqQu-3-

What did you expect to see?

No output

What did you see instead?

STDERR:

Usage of app:

/usr/local/Cellar/go/1.8.2/libexec/src/flag/flag.go

var Usage = func() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	PrintDefaults()
}

Usage function disregards f.Out() in favour of os.Stderr.

The correct code should be:

var Usage = func() {
	fmt.Fprintf(f.out(), "Usage of %s:\n", os.Args[0])
	PrintDefaults()
}
@bradfitz bradfitz changed the title flag.Usage() disregards custom output flag: global Usage func disregards FlagSet.SetOutput Jul 13, 2017
@bradfitz bradfitz added Documentation NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. labels Jul 13, 2017
@bradfitz bradfitz added this to the Go1.10 milestone Jul 13, 2017
@bradfitz
Copy link
Contributor

The flag.Usage global variable was in the original Go 1.0:

var Usage = func() {
        fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
        PrintDefaults()
}

Go 1.2 introduced the CommandLine global variable:

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

The documentation of FlagSet.SetOutput says:

https://golang.org/pkg/flag/#FlagSet.SetOutput

SetOutput sets the destination for usage and error messages. If output is nil, os.Stderr is used.

The problem @vearutop hits is modifying flag.CommandLine which uses the implicit flag.Usage, even though Usage is not associated with CommandLine.

The correct code should be:

I think you mean:

var Usage = func() {
	fmt.Fprintf(CommandLine.out(), "Usage of %s:\n", os.Args[0])
	PrintDefaults()
}

@gopherbot
Copy link

CL https://golang.org/cl/48390 mentions this issue.

@golang golang locked and limited conversation to collaborators Aug 8, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Documentation FrozenDueToAge NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Projects
None yet
Development

No branches or pull requests

3 participants