golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.04k stars 17.67k forks source link

cmd/go: Documentation should make it clearer that the go tool works best on packages #43970

Open vdobler opened 3 years ago

vdobler commented 3 years ago

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

NA

Does this issue reproduce with the latest release?

Yes

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

NA

Problem description

There seem to be a growing set of users who think that the arguments to the various subcommands of the go tool should be source code file names (or at least can be source code files without any drawbacks). This leads to a lot of questions why something doesn't work out as expected. The following is an anecdotic list of questions I heave seen in the past years:

The tutorial has been updated already in commit 713e774d to work on packages only but it seems this information doesn't really reach the intended audience.

When I heard of Go a decade ago the package system was one of the first things I read about and was impressed how transitive dependencies are are handled and how clean testing and platform specific code was. Building Go code was always go build without arguments for me. And this "just works". But it seems as if a lot of newcomers to the language are used to work with source code files and lots of (external) tutorials promoting go run main.go together with the possibility of using go build with source files too might have lead to the assumption that the "go tools works on files (as most other languages actually do)".

I think there is not enough "warning" on golang.org that explains how Go and the go tool is different in handling its compilation units and that the go tool works best if applied to packages.

For a Go veteran this is not news and nothing wich needs to be spelled out in detail but I think lot's of newcomers are confused about packages and the fact that the go tool works quite well on files for simple cases (as they are used from other languages) but has some sharp edges. And after 3 month of go run main.go this file-based thinking sets in and ultimately leads to frustration because Go's compilation unit is a package (which de facto is a folder).

(An other frequent question is about "software architecture" in the sense of "which folder layout for my source code should my project use" which I think also indicates that the concept of a Go package is often only poorly understood. Other question regarding "sub-packages" or "parent-packages" also hint in this direction. The hassle to understand a Go module as nothing more than a set of packages with the same lifecycle versioned together might also come from not grasping the concept of a package.)

Unfortunately I cannot point to one (or several) documents on the website and say "here it needs a paragraph explaining concept of a package and here we have to add the Use-the-go-tool-on-packages-only-! warning sign."

There are good reasons to do a go run gen.go or use go build with files but probably these should be the exception and the official documentation should make it very clear: Use the go tool on packages only!

bcmills commented 3 years ago

CC @stevetraut @jayconrod @matloob

stevetraut commented 3 years ago

@vdobler, thanks for the note. I'm focusing on docs. Here are the key bits I read from your note:

Each of these is, in some way, addressed in plans for new content. I think there's a lot of useful content about packages and modules (for example) embedded in blog posts and articles on the site, but it can be hard to find.

vdobler commented 3 years ago

@stevetraut Thanks for the summary, it almost captures my issue:

The third bullet is overly generic and a common problem and not the main issue I wanted to address.

The first and second bullet are the main issues and probably should be combined. Go is package oriented: Visibility is package based. Import is package based, source code layout is package based. Testing is package based. Build is package based. Code reuse is package based. So the correct way to test, build and run Go code is always a plain go build or go test only and maybe a go run .. Working with source code files is wrong (but possible to accommodate for edge cases, expert usage and toy cases): You cannot import them, you cannot test them and building them might not do what you expect it to do based on experience with other languages. This package orientation is a distinguishing feature and---as such---underrepresented in the documentation.

This lead to frustrating experience for newcomers who think go run main.go might be the recommended (or even just a safe) way to "execute Go code". Newcomers should never use go run.

(Modules might be "underdocumented" but the idea of what modules are and how to use them is basically trivial once someone understands packages, import paths (as package-identity) and same lifecycle / evolving in lockstep.)