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

cmd/go: go doc -h is inconsistent and slightly broken #55985

Open
mvdan opened this issue Oct 1, 2022 · 5 comments
Open

cmd/go: go doc -h is inconsistent and slightly broken #55985

mvdan opened this issue Oct 1, 2022 · 5 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@mvdan
Copy link
Member

mvdan commented Oct 1, 2022

$ go version
go version devel go1.20-5f566d35bf Sat Oct 1 08:32:46 2022 +0000 linux/amd64

In general, go command -h is very short at just a few lines, pointing instead to go help command for the longer help text. However, go doc -h is an outlier.

$ for cmd in bug build clean doc env fix fmt generate get install list mod work run test tool version vet; do echo "\$ go $cmd -h"; go $cmd -h; ech
o; done
$ go bug -h
usage: go bug
Run 'go help bug' for details.

$ go build -h
usage: go build [-o output] [build flags] [packages]
Run 'go help build' for details.

$ go clean -h
usage: go clean [clean flags] [build flags] [packages]
Run 'go help clean' for details.

$ go doc -h
Usage of [go] doc:
	go doc
	go doc <pkg>
	go doc <sym>[.<methodOrField>]
	go doc [<pkg>.]<sym>[.<methodOrField>]
	go doc [<pkg>.][<sym>.]<methodOrField>
	go doc <pkg> <sym>[.<methodOrField>]
For more information run
	go help doc

Flags:
  -all
    	show all documentation for package
  -c	symbol matching honors case (paths not affected)
  -cmd
    	show symbols with package docs even if package is a command
  -short
    	one-line representation for each symbol
  -src
    	show source code for symbol
  -u	show unexported symbols as well as exported
exit status 2

$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.

$ go fix -h
usage: go fix [-fix list] [packages]
Run 'go help fix' for details.

$ go fmt -h
usage: go fmt [-n] [-x] [packages]
Run 'go help fmt' for details.

$ go generate -h
usage: go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]
Run 'go help generate' for details.

$ go get -h
usage: go get [-t] [-u] [-v] [build flags] [packages]
Run 'go help get' for details.

$ go install -h
usage: go install [build flags] [packages]
Run 'go help install' for details.

$ go list -h
usage: go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
Run 'go help list' for details.

$ go mod -h
go mod -h: unknown command
Run 'go help mod' for usage.

$ go work -h
go work -h: unknown command
Run 'go help work' for usage.

$ go run -h
usage: go run [build flags] [-exec xprog] package [arguments...]
Run 'go help run' for details.

$ go test -h
usage: go test [build/test flags] [packages] [build/test flags & test binary flags]
Run 'go help test' and 'go help testflag' for details.

$ go tool -h
usage: go tool [-n] command [args...]
Run 'go help tool' for details.

$ go version -h
usage: go version [-m] [-v] [file ...]
Run 'go help version' for details.

$ go vet -h
usage: go vet [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]
Run 'go help vet' for details.
Run 'go tool vet help' for a full list of flags and analyzers.
Run 'go tool vet -help' for an overview.

Note that go doc -h prints many more lines than the others, but also, it prints an exit status 2 line which seems wrong. The latter seems to be because it combines CustomFlags: true with executing go tool doc -h, which means that the flag parsing happens in the child process, and the parent process simply shows the non-zero exit status.

We probably should:

  • change go doc -h to show a few lines like the others, for consistency
  • change go doc to never show exit status 2 for flag errors like go doc -h or go doc -badflag

Also note that go tool doc -h is slightly confusing; unlike others such as go tool fix -h, it shows the help for go doc rather than go tool doc.

cc @robpike @bcmills @matloob

@dmitshur dmitshur added this to the Backlog milestone Oct 1, 2022
@dmitshur dmitshur added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Oct 1, 2022
@robpike
Copy link
Contributor

robpike commented Oct 2, 2022

Doesn't seem like much of a problem to me. The output is helpful, arguably more so than the others'. I wouldn't call it "broken".

Is vet problematic for you too? Because it's also different, and harmlessly so.

@mvdan
Copy link
Member Author

mvdan commented Oct 2, 2022

At a minimum, the exit status 2 seems wrong.

I wouldn't mind if go doc -h resembled go vet -h. But I do think we want to be consistent for the sake of not confusing our users. I don't claim that one way is better than the other, but go doc -h is the outlier today.

@mvdan
Copy link
Member Author

mvdan commented Oct 6, 2022

I was just stumped at go doc -h hanging for multiple seconds when my current directory was a Go package with a large tree of dependencies. I thought to myself that perhaps it was loading the entire package tree and filling the build cache, which would certainly be a bug.

Here's a small repro, using https://github.com/mvdan/sh/tree/master/interp as a sample Go package inside a third party module with some imports:

$ go clean -cache -modcache
$ time go doc -h
[...]

real	0m0.348s
user	0m0.069s
sys	0m0.020s
$ go clean -cache -modcache
$ time go help doc
[...]

real	0m0.005s
user	0m0.007s
sys	0m0.000s

In this particular case, the wait was about a third of a second, because the package and its dependencies are smaller - go list -deps shows 63 packages. With the larger package, where go doc -h with an empty cache took a staggering 17s, go list -deps shows 627 packages.

@nickjwhite
Copy link

I wouldn't mind if go doc -h resembled go vet -h. But I do think we want to be consistent for the sake of not confusing our users. I don't claim that one way is better than the other, but go doc -h is the outlier today.

I'm not sure which way is best, but thought I'd share my experience. I hadn't noticed the usage() part of doc recently when writing a change (not having considered someone running go doc -h), and just focused on updating the documentation in src/cmd/go/internal/doc/doc.go. In my case it wouldn't have made any difference, but having duplicated documentation in different places does increase the chance of documentation differing in different places.

One alternative option would be to grab some documentation (perhaps just the UsageLine straight from the base.Command defined in src/cmd/go/internal/doc/doc.go.

Consistency between tools would be nice, but I'd lean towards making the others at least print their basic usage, rather than just essentially remove -h from all tools.

@nickjwhite
Copy link

I was just stumped at go doc -h hanging for multiple seconds when my current directory was a Go package with a large tree of dependencies. I thought to myself that perhaps it was loading the entire package tree and filling the build cache, which would certainly be a bug.

That looks to be because dirsInit() is called before the flag parsing. From a brief read of the code it looks like it could be started after flag parsing (though the extras would need to be passed to do() in order for the tests to be set up appropriately), which would solve your particular case of go doc -h being too slow.

For the wider issue of initial go doc running being slow from a package with many dependencies, you'd know better than me but I'd imagine that deserves a separate issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants