16

I have a go package located on my filesystem (not in the $GOPATH), called bitbucket.org/me/awesome.

~/awesome> tree
.
├── main.go
├── go.mod
├── go.sum
├── subpackageA
│   └── main.go

My go.mod looks like:

module bitbucket.org/me/awesome

require (
       ... # lots of external dependencies
)

replace bitbucket.org/me/awesome => ./

In main.go in my top-level directory, I call a subpackage like follows:

import "bitbucket.org/me/awesome/subpackageA"

which all seems pretty normal. go get works. However, when I clone this entire repository somewhere else (say in a Docker image) and run go get for the first time, I get errors like:

package bitbucket.org/me/awesome/subpackageA: https://api.bitbucket.org/2.0/repositories/me/awesome?fields=scm: 403 Forbidden,

which means it's not using the local filesystem version of the packages, even though I told it to with the replace directive in the go.mod file.

What am I doing wrong? How do I ensure that subpackages are used from the filesystem instead of attempting to be fetched from the internet?

poy
  • 10,063
  • 9
  • 49
  • 74
atp
  • 30,132
  • 47
  • 125
  • 187
  • 2
    Yoe seem to have a replace directive for bitbucket.org/me/awesome only but the problem is with bitbucket.org/me/awesome/subpackageA. Do not think of a package in a folder as a subpackage: It is not. It is a standalone package _without_ _any_ relation to what is in the "parent" folder. – Volker Nov 19 '18 at 06:06
  • @Volker thanks, that was the tip that fixed this problem for me (adding other `replace` lines for subpackages). Do you want to add your comment as an answer? – atp Nov 19 '18 at 09:11
  • 1
    I don't quite understand this problem statement. It seems all the packages in question here are all in the same `bitbucket.org/me/awesome` module, and packages within the same module should find each other automatically without needing a `replace` directive. – thepudds Aug 01 '19 at 20:24
  • (Also, `replace` directives only operate on _modules_ as the left-side and right-side arguments, and not on subpackages or packages, unless a package is in the root of the module, in which case the package path and module path are the same, but even then the `replace` directive is really operating at the module level). – thepudds Aug 01 '19 at 20:29
  • There is a bit more [here](https://stackoverflow.com/a/57314494/11210494) on how packages find each other within the same module, and how that relates overall module structure. – thepudds Aug 01 '19 at 20:31

2 Answers2

16

Go has no (real) notion of "subpackage". All packages are basically treated equal. This means that a replace bitbucket.org/me/awesome does not influence package bitbucket.org/me/awesome/subpackageA as these are two individual, unrelated packages. The folder layout does not introduce a relation of subpackageA to awsome, or the other way around *).

So you need to add an individual replace directive for subpackageA

replace bitbucket.org/me/awesome/subpackageA => ./subpackageA

*) Nitpicking for absolute correctness: Folder layout does have influence for folders named internal (cannot be imported from other projects), for folders named vendor (which may contain vendored packages) and searching for a go.mod file stops at the repo root.

Volker
  • 40,468
  • 7
  • 81
  • 87
  • Where should I put this code: `replace bitbucket.org/me/awesome/subpackageA => ./subpackageA` Or is it just a step? Pls be clear. – Rajesh Paul Aug 25 '22 at 09:39
  • @RajeshPaul in go.mod. Please read the Tutorials in go.dev/doc carefully (once more). – Volker Aug 25 '22 at 10:13
3

For another approach, you can have go.mod like this:

module awesome

Then call subpackage like this:

import "awesome/subpackageA"

https://golang.org/doc/code.html

Zombo
  • 1
  • 62
  • 391
  • 407