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: allow go run . in module mode without a go.mod file #36513

Open
go101 opened this issue Jan 12, 2020 · 27 comments
Open

cmd/go: allow go run . in module mode without a go.mod file #36513

go101 opened this issue Jan 12, 2020 · 27 comments
Labels
Milestone

Comments

@go101
Copy link

@go101 go101 commented Jan 12, 2020

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

$ go version
go version go1.14beta1 linux/amd64

Does this issue reproduce with the latest release?

Yes

What did you do?

  • Create a simple hello world project with only one main.go file.
  • Set GO111MODULE=on
  • Run go run . in the project folder.

What did you expect to see?

Run okay.

What did you see instead?

go: cannot find main module; see 'go help modules'

or for a git repository

go: cannot find main module, but found .git/config in /path/to/projects/helloworld
	to create a module there, run:
	go mod init
@mvdan
Copy link
Member

@mvdan mvdan commented Jan 12, 2020

Why are you setting GO111MODULE=on? A module requires a go.mod file, so it seems like you have conflicting objectives here.

In any case, it seems like you disagree with #32027. That discussion happened a while ago, though.

@TapirLiu
Copy link
Contributor

@TapirLiu TapirLiu commented Jan 12, 2020

Some people might have set it on globally before for some other reasons.
I just found this issue from a PR of one my project.

@TapirLiu
Copy link
Contributor

@TapirLiu TapirLiu commented Jan 12, 2020

The current design also causes inconveniences in writing some Go tutorials with a simple Go file (and might have caused for some old tutorials). They must remind readers to create a go.mod file if GO111MODULE=on is set.

If some new gophers have set GO111MODULE=on before reading such old tutorials, the result might frustrate them at least for awhile.

@mvdan
Copy link
Member

@mvdan mvdan commented Jan 12, 2020

I think it depends on what exactly the user is doing. If they need third party dependencies, requiring a go.mod sounds correct.

If they don't need third party dependencies, i.e. they use the standard library alone, I agree that a go.mod is largely not needed right now. You could work around that by asking the user to set GO111MODULE=off.

But it would still be a good idea to use a go.mod file in the long term, even if it's just for simple examples. It will be required to use newer language features, for example. See https://golang.org/doc/go1.13#language.

@TapirLiu
Copy link
Contributor

@TapirLiu TapirLiu commented Jan 12, 2020

Yes, the go.mod file have some benefits, but not for new gophers to learn Go.

At least, the error message should not depend on whether or not there is a .git subfolder. The help message should also be printed for both cases. And even for the git repository case, the printed help message is also too unfriendly for new gophers. It is better to provide an example, such as go mod init my.module.

@jayconrod
Copy link
Contributor

@jayconrod jayconrod commented Jan 13, 2020

I'd recommend against setting GO111MODULE=on globally. That was useful for working on modules checked out into GOPATH in Go 1.12 or earlier, but since GO111MODULE=auto was changed in 1.13, I don't think it makes sense now. Maybe in a few specific cases for tools, but not generally. Hopefully people who have it set know the implications, so I wouldn't expect that tutorials need to be written for them. If any documentation recommends new users set GO111MODULE=on, we should fix that.

This specific change in behavior was #32027. In short, if a user has GO111MODULE=on set explicitly, and there's no go.mod file in the current directory or in any parent, you can only build or import packages in the standard library or packages specified as .go files on the command line. So for example, this works:

$ cat >hello.go <<EOF
package main

import "fmt"

func main() {
  fmt.Println("hello")
}
EOF

$ go run hello.go
hello

Import paths in modules other than std and cmd won't work. That includes relative imports and patterns.

$ go run
go run: no go files listed
$ go run .
go: cannot find main module; see 'go help modules'
$ go list golang.org/x/tools/gopls
can't load package: cannot find module providing package golang.org/x/tools/gopls: working directory is not part of a module
$ go list ./...
go: cannot find main module; see 'go help modules'

The rationale for this change was that early on, people would set GO111MODULE=on, not create a go.mod file, then find that everything is very slow: we need to look up module paths and versions for every import on every command, since there's nowhere to write down dependencies.

I don't think this necessarily means go build . or go run . should not work, but fixing this would probably involve adding a significant special case, and it would be risky to do that this late in the cycle.

@bcmills @matloob WDYT? We might want to do this if/when GOPATH mode is deprecated, since GO111MODULE=on will be the only mode after that.

@jayconrod jayconrod added this to the Unplanned milestone Jan 13, 2020
@bcmills
Copy link
Member

@bcmills bcmills commented Jan 22, 2020

At the very least, we would need to decide what language version to use in module mode for a package in a directory outside of any module.

We would also need to determine the effective import path for such a package for debug info and build caching. (Perhaps the same import path that we generate in GOPATH mode today?)

@go101
Copy link
Author

@go101 go101 commented Jan 27, 2021

It looks this problem has been fixed in go1.16beta1.

@go101
Copy link
Author

@go101 go101 commented Feb 5, 2021

A new problem if go.mod doesn't present:

// main.go

package main

import _ "embed"

//go:embed main.go
var b []byte

func main() {
	println(string(b))
}

// error: pattern main.go: cannot embed irregular file main.go

The embedding feature is not usable without a go.mod file.

@derrickb
Copy link

@derrickb derrickb commented Apr 4, 2021

Just want to say I came back to a go project that I (thankfully) rarely need to touch more than once per year, and found it really confusing to get back into it and just build something.

go version go1.16.3 windows/amd64

No matter what I had set for GO111MODULE, I kept getting an error about go.mod not being preset. I refer to one external package (an ancient image resizing one that is no longer maintained), and both the vscode extension and the go compiler were tripping up over this module file thing. Googling wasn't super helpful here. I eventually got past this by googling and stumbling through setting up a module, but I now have more files and a package.json-like setup that I don't really understand.

I second the OP, this isn't really user-friendly for simple projects.

@go101
Copy link
Author

@go101 go101 commented Apr 5, 2021

@derrickb it looks running simple go files doesn't need a go.mod file with Go toolchian v1.16. Maybe yours is another problem?

@opennota
Copy link

@opennota opennota commented Apr 5, 2021

@go101
go run main.go works, but go run . doesn't.

@go101
Copy link
Author

@go101 go101 commented Apr 5, 2021

Yes. Sorry, I forgot that.

@derrickb
Copy link

@derrickb derrickb commented Apr 5, 2021

@go101 I need to mess around with it more... my project is just three small .go files and using go build but it required a mod file no matter what combination of env variables I had.

@opennota
Copy link

@opennota opennota commented Apr 5, 2021

@derrickb go build *.go should work. It's not very newbie-friendly, though.

@go101
Copy link
Author

@go101 go101 commented Apr 5, 2021

go build *.go doesn't work on Windows.

@opennota
Copy link

@opennota opennota commented Apr 6, 2021

Yes, on windows you'd have to list the files individually: go build a.go b.go main.go ...

@jayconrod
Copy link
Contributor

@jayconrod jayconrod commented Apr 6, 2021

There's been some renewed attention on this issue, since GO111MODULE defaults to on in 1.16. It's not clear to me what folks want to change though.

In module-aware mode, if there is no go.mod file, you can still go build (or go run, etc) a package comprised of individual .go files listed on the command line (go build a.go b.go). The package can only import packages from the standard library.

This last restriction was added in Go 1.14 (#24031). Since there's no go.mod file, there's no place for the go command to save which version of each dependency is used, so before that, it went out to the network to look up every missing import. This was slow and non-deterministic, and we didn't feel that it was a good experience for beginners. An alternative would be using modules already downloaded into the module cache, but there's potential to use unexpectedly old versions, so we decided against that.

For this issue, it seems reasonable to me to let go build and other commands accept an absolute or relative path (go build . or go build ./foo) that would refer to the package in that directory. The package still wouldn't be able to import anything outside the standard library.

Does that sound reasonable?

@eliasnaur
Copy link
Contributor

@eliasnaur eliasnaur commented Apr 6, 2021

For this issue, it seems reasonable to me to let go build and other commands accept an absolute or relative path (go build . or go build ./foo) that would refer to the package in that directory. The package still wouldn't be able to import anything outside the standard library.

Does that sound reasonable?

Yes, please. The distinction between a list of .go files and a path, with respect to the no-go.mod mode, is surprising to me; I learned about it from your message.

@thepudds
Copy link

@thepudds thepudds commented Apr 6, 2021

Hi @jayconrod I agree this would be a nice and friendly improvement.

For this issue, it seems reasonable to me to let go build and other commands accept an absolute or relative path (go build . or go build ./foo) that would refer to the package in that directory.

One clarifying question: would this also apply to commands like go build without any arguments? (I think that might be implied by what you wrote, but just trying to make it explicit, vs. perhaps there is some reason that wouldn’t work that is not immediately springing to mind for me 😅…)

@jayconrod
Copy link
Contributor

@jayconrod jayconrod commented Apr 7, 2021

@thepudds Yes, go build would be equivalent to go build ., which should work.

@jayconrod
Copy link
Contributor

@jayconrod jayconrod commented Apr 13, 2021

Discussed this with @bcmills, @matloob, and @_rsc. I think we're all agreed this is a good idea.

One clarification, go run . should still apply build constraints, same as if you'd run go run . inside a module. So it won't be exactly equivalent to go run *.go, which does not apply build constraints.

@jayconrod jayconrod changed the title cmd/go: it is inconvenient and unfriendly to require a simple program must have a go.mod file cmd/go: allow go run . in module mode without a go.mod file Apr 13, 2021
@jayconrod jayconrod removed this from the Unplanned milestone Apr 13, 2021
@jayconrod jayconrod added this to the Backlog milestone Apr 13, 2021
@pawan-saxena

This comment was marked as off-topic.

@mjaggard
Copy link

@mjaggard mjaggard commented Jul 14, 2021

Well this has caused my first experience of Go to be awful. I just checked out a project (https://github.com/rancher/migration-tools) and hoped to run it but I have no clue how. I figured that I needed to run glide install but then I can't find any incantation that will run the actual project. I know the project likely needs updating but it should be possible to run old programs.

@derrickb
Copy link

@derrickb derrickb commented Jul 14, 2021

Yeah this made go a little less "pick up and go" which is such a shame, as that was a great feature of the language and tools.

@bcmills
Copy link
Member

@bcmills bcmills commented Jul 14, 2021

@mjaggard, what were the commands that you ran and what was the output produced by those commands?

Even today, go run . within a checkout of a repo ought to suggest running go mod init, and once that's done go run . should work. Did go run . not suggest go mod init, or did you run into other problems from that point?

@mjaggard
Copy link

@mjaggard mjaggard commented Jul 14, 2021

$ go mod init
go: cannot determine module path for source directory /Users/mat/dev/migration-tools (outside GOPATH, module path must be specified)

Example usage:
	'go mod init example.com/m' to initialize a v0 or v1 module
	'go mod init example.com/m/v2' to initialize a v2 module

Run 'go help mod init' for more information.
$ go mod init .
go: invalid module path ".": is a local import path

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet