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: clarify go.mod documentation for trivial relative modules #27274

Closed
gazed opened this issue Aug 27, 2018 · 7 comments

Comments

Projects
None yet
6 participants
@gazed
Copy link

commented Aug 27, 2018

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

go version go1.11 darwin/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="/Users/rust/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/rust/code"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/rust/code/modtest/b/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 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/_d/8n_wrc4n32d1rgx80bn6hsl80000gn/T/go-build056371648=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Created two modules a and b in the same directory, not on the GOPATH.

Module a contains a.go, go.mod:

~/code/modtest/a: cat a.go
package a

func Hello() string {
	return "Hello"
}
~/code/modtest/a: cat go.mod
module a

Module b contains b.go, go.mod:

~/code/modtest/b: cat b.go
package main

import (
    "fmt"

    "a"
)

func main() {
	fmt.Printf("%s\n", a.Hello())
}
~/code/modtest/b: cat go.mod 
module b

require ../a v0.0.0

What is the proper syntax for the line require ../a v0.0.0 in this particular case?
The closest I found in the docs (go help modules, go help go.mod, go help mod) was from go help importpath:

Relative import paths

An import path beginning with ./ or ../ is called a relative path.
The toolchain supports relative import paths as a shortcut in two ways.

First, a relative path can be used as a shorthand on the command line.
...

Second, if you are compiling a Go program not in a work space,
you can use a relative path in an import statement in that program
to refer to nearby code also not in a work space.
This makes it easy to experiment with small multipackage programs
outside of the usual work spaces, but such programs cannot be
installed with "go install" (there is no work space in which to install them),
so they are rebuilt from scratch each time they are built.
To avoid ambiguity, Go programs cannot use relative import paths
within a work space.

It is unclear to me if the second case is supposed to apply in this situation.

What did you expect to see?

I expect this to compile and run similarly to how it works with the existing GOPATH.
For example, copying the modules to the GOPATH gives the following:

~/code/src: cd a
~/code/src/a: go build
~/code/src/a: cd ../b
~/code/src/b: go build
~/code/src/b: ./b
Hello

What did you see instead?

~/code/modtest: cd a
~/code/modtest/a: go build
~/code/modtest/a: cd ../b
~/code/modtest/b: go build
go: ../a@v0.0.0: unrecognized import path "../a" (https fetch: Get https://../a?go-get=1: dial tcp: lookup ..: no such host)
go: error loading module requirements
~/code/modtest/b: 
@thepudds

This comment has been minimized.

Copy link

commented Aug 27, 2018

Setting aside for the moment the question of whether the documentation could be improved, here is a concrete example that might help.

Sample file structure on my local system, all outside of GOPATH:

    /tmp/playground/hello
    |-- go.mod
    `-- hello.go
    /tmp/playground/goodbye
    |-- go.mod
    `-- goodbye.go

And the contents of /tmp/playground/hello/go.mod:

    module example.com/me/hello

    require (
     example.com/me/goodbye v0.0.0
     rsc.io/quote v1.5.2
    )

    replace example.com/me/goodbye => ../goodbye

See a longer discussion and the rest of the example here (which is a runnable example if you are interested):
https://groups.google.com/d/msg/golang-nuts/1nYoAMFZVVM/eppaRW2rCAAJ

@thepudds

This comment has been minimized.

Copy link

commented Aug 27, 2018

@gopherbot please add label modules

@gopherbot gopherbot added the modules label Aug 27, 2018

@gazed

This comment has been minimized.

Copy link
Author

commented Aug 27, 2018

Thank you for the working module solution. Setting aside for the moment whether or not this is the canonical solution moving forward, it breaks when moving the code to the GOPATH, making the code non-backwards compatible. Is there another solution that works without changing the source code files? Otherwise it feels like a missing feature or a bug, instead of "a me not finding the right documentation" problem as I had assumed.

Here is the original problem source updated to work with modules.

~/code/modtest/a: cat a.go
package a

func Hello() string {
	return "Hello"
}
~/code/modtest/a: cat go.mod 
module example.com/me/a
~/code/modtest/a: go build
~/code/modtest/a: cd ../b
~/code/modtest/b: cat b.go 
package main

import (
    "fmt"
    
    "example.com/me/a"
)

func main() {
	fmt.Printf("%s\n", a.Hello())
}
~/code/modtest/b: cat go.mod 
module example.com/me/b

require example.com/me/a v0.0.0

replace example.com/me/a => ../a
~/code/modtest/b: go build
~/code/modtest/b: ./b
Hello

Moving both modules into the GOPATH results in the following:

~/code/src: cd a
~/code/src/a: go build
~/code/src/a: cd ../b
~/code/src/b: go build
b.go:6:2: cannot find package "example.com/me/a" in any of:
	/usr/local/go/src/example.com/me/a (from $GOROOT)
	/Users/rust/code/src/example.com/me/a (from $GOPATH)
@thepudds

This comment has been minimized.

Copy link

commented Aug 27, 2018

If you return to the GOPATH world, then you would place the go source code back where Go 1.10 and earlier would expect it based on the import paths you are using in the code.

E.g., something like $GOPATH/src/example.com/me/a/a.go?

If you don't like that example.com, then you don't need to use it in your go.mod and corresponding import paths.

And sorry if I am misunderstanding; this is all new...

@gazed

This comment has been minimized.

Copy link
Author

commented Aug 27, 2018

Thank you for your patience, adding just the replace a => ../a works. Thank you!

~/codeold/modtest: cd a
~/codeold/modtest/a: cat a.go 
package a

func Hello() string {
	return "Hello"
}
~/codeold/modtest/a: cat go.mod 
module a
~/codeold/modtest/a: cd ../b
~/codeold/modtest/b: cat b.go
package main

import (
    "fmt"
    "a"
)

func main() {
	fmt.Printf("%s\n", a.Hello())
}
~/codeold/modtest/b: cat go.mod
module b

require a v0.0.0

replace a => ../a

@FiloSottile FiloSottile added this to the Go1.12 milestone Aug 30, 2018

@FiloSottile FiloSottile changed the title cmd/go: Please clarify go.mod documentation for trivial relative modules. cmd/go: clarify go.mod documentation for trivial relative modules Aug 30, 2018

@klaus

This comment has been minimized.

Copy link

commented Aug 31, 2018

it's important to note, that you need the "require" AND the "replace" in the go.mod file.
I like to add them via the commandline, the commands should be encouraged and documented with examples.

the go mod init command does not populate go.mod with packages it cannot resolve. Therefore you must do:

go mod edit require example.com/post-adressdaten
go mod edit -replace example.com/post-adressdaten=../post-adressdaten/

@myitcv

This comment has been minimized.

Copy link
Member

commented Sep 7, 2018

@klaus

I like to add them via the commandline, the commands should be encouraged and documented with examples.

They are documented under go help mod edit

That a replace requires (!) a require is something that is going to be addressed in Go 1.12 via #26241

I'm going to close this issue on the basis I think all questions have been answered, but please shout it not.

@myitcv myitcv closed this Sep 7, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.