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: 'cannot find module for path' when importing from subdirectories #26645

Closed
markkuit opened this Issue Jul 27, 2018 · 3 comments

Comments

Projects
None yet
4 participants
@markkuit

markkuit commented Jul 27, 2018

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

go version go1.11beta2 linux/amd64

Does this issue reproduce with the latest release?

Yes.

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

GOARCH="amd64"
GOBIN=""
GOCACHE="/home/markkuit/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/markkuit/go/"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/tmp/gomodsubdirs/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build236792179=/tmp/go-build -gno-record-gcc-switches"

What did you do?

The issue arises when using modules when having imports from subdirectories. I created a easy to reproduce example:

/tmp/gomodsubdirs/go.mod
module testmodule.local/gomodsubdirs

/tmp/gomodsubdirs/main.go

package main

import (
	"./subdir"
	"fmt"
)

func main() {
	fmt.Println("Printing from main!")
	subdir.Print()
}

/tmp/gomodsubdirs/subdir/subdir.go

package subdir

import "fmt"

func Print() {
	fmt.Println("Printing from subdir!")
}

What did you expect to see?

I expected build to be successful both with and without modules, but it looks like putting code in subdirectories is troublesome for go modules (or I'm doing something wrong). I tend to do this quite a lot when I have a package in a subdirectory with a lot of files (mostly boilerplate code), which isn't however worthy of being a separate package itself or is too strictly related to the main package to be put apart from it. Note that I tried having a go.mod inside the subdirectory as well (both empty and filled), but it made no difference.

What did you see instead?

> go build main.go
build .: cannot find module for path _/tmp/gomodsubdirs/subdir
> env GO111MODULE=off go build main.go
> ./main
Printing from main!
Printing from subdir!

@oiooj oiooj added the modules label Jul 27, 2018

@rsc

This comment has been minimized.

Contributor

rsc commented Jul 28, 2018

Sorry but this is working as intended. This kind of "relative import" was something we had in the very early days of go, before there was a go command, but when we moved to the go command and GOPATH we finally had a way to give a fully-qualified path for imports, at least within GOPATH, and we standardized on that fully-qualified form for tools and such. The relative imports still worked outside GOPATH, essentially out of a combination of necessity and neglect, but they didn't work as well. Among other things, until Go 1.10 there was no build caching, so that builds were slower. Many tools don't handle them right. But they were left in because otherwise there was no name for that subdirectory.

In modules, there finally is a name for the subdirectory. If the parent directory says "module m" then the subdirectory is imported as "m/subdir", no longer "./subdir".

I do apologize that we don't have something that works both ways, but we definitely want to preserve the property for the vast majority of Go code that imports are fully-qualified, and so we don't want moving to modules to lose that property. Instead moving from "outside GOPATH one-off directories" to modules requires using the newly-available fully-qualified name.

Best,
Russ

@rsc rsc closed this Jul 28, 2018

@markkuit

This comment has been minimized.

markkuit commented Jul 28, 2018

This actually makes perfect sense, and I do agree it was a choice that had be taken. What I was worried about was not having the possibility to organize code in subdirectories anymore; instead, I can confirm specifying the full import path achieves the goal - even if the module isn't under any VCS yet.

I'll take this opportunity to thank you (and the whole team) for your continued efforts, and thank you for clarifying this issue.

@ccll

This comment has been minimized.

ccll commented Dec 14, 2018

In modules, there finally is a name for the subdirectory. If the parent directory says "module m" then the subdirectory is imported as "m/subdir", no longer "./subdir".

How about sibling packages?
I have a folder structure:

- Root
  |--- mod1
       |--- go.mod
  |--- mod2
       |--- go.mod

I couldn't find a way to import mod2 from mod1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment