`go get` and workspaces (`go.work`)

1,222 views
Skip to first unread message

Jan

unread,
Jul 11, 2023, 3:49:34 AM7/11/23
to golang-nuts
hi all,

When using a `go get` in a project (module) that has a `go work` configured, I'm getting errors "cannot find module providing package ...", for the packages that are located on `go work use ...` locations. Meaning, `go get` seems to ignore (?) `go.work` file.

Likely this is deliberate and I'm missing some point, but ... for my use case, I would love to have `go get` ignore the packages that are imported from directories in `go.work`, and just "get" the other ones.

Is there a way to have that ? (I couldn't find any flag in `go get`). Or any other ideas ?

many thanks!
Jan

ps.: Here how to reproduce the issue:

Director "~/work/a/"

$ go mod init "github.com/joe/a"
$ cat > main.go
package main
import (
        "fmt"
        "github.com/joe/b"
)

func main() {
        fmt.Printf("Hello from joe/a!\n")
        b.Message()
}
$ go work init ; go work use .  ~/work/b

In directory "~/work/b":

$ go mod init "github.com/joe/b"
$ cat > b.go
package b
import "fmt"
func Message() {
        fmt.Printf("Hello from joe/b!\n")
}

Back to directory "~/work/a":

$ go run .
Hello from joe/a!
Hello from joe/b!

$ go get
github.com/joe/a imports
        github.com/joe/b: cannot find module providing package github.com/joe/b


A bit more context, in case it matters: I don't need to `go get` to get anything for the packages in `go.work`, but I (think) need it to get any potential missing other packages. I run `go get` (without specifying the packages) each time before executing a Jupyter notebook cell (in GoNB a jupyter notebook kernel), because I don't know ahead of time which new packages need to be fetched. 

Also curiously, if I use a `replace` directive in `go.mod` then `go get` works fine, it seems to ignore the replaced package. In my example:

$ go mod edit --replace github.com/job/b=/home/janpf/work/b

But a `replace` directive in `go.work` doesn't seem parsed by `go get`:

$ go work edit --replace github.com/job/b=/home/janpf/work/b

Howard C. Shaw III

unread,
Jul 11, 2023, 8:46:11 AM7/11/23
to golang-nuts
I don't think you need to run go get there at all - just run go mod tidy, and then when you go build, if it needs something it will get it. If you need to download without building, go mod download will do that.

Howard

Jan

unread,
Jul 11, 2023, 11:49:21 AM7/11/23
to golang-nuts
Thanks for the reply, but I'm not sure what exactly what you mean.

In my example it's not that I need to `go get` anything for my locally stored packages (so I don't need to get `github.com/joe/b`). Rather, I need `go get` for other packages. But it (`go get`) fails on the local stored packages (`github.com/joe/b` in the example), it doesn't fetch the other packages either. Does it make sense ?

Would you mind clarifying ?

Btw, I tried `go mod tidy` in the `~/work/a` directory, in the example I created and I get:

```
$ go mod tidy
go: finding module for package github.com/joe/b
github.com/joe/a imports
        github.com/joe/b: cannot find module providing package github.com/joe/b: module github.com/joe/b: git ls-remote -q origin in /home/janpf/src/go/pkg/mod/cache/vcs/ec7e851af7fd4aeb2a38ed2f81b738f5af4402954d5c2f4c363f5fb9f1b4583c: exit status 128:
        fatal: could not read Username for 'https://github.com': terminal prompts disabled
Confirm the import path was entered correctly.
If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.
```

In my case let's assume I modify my program `~/work/a/main.go` to use an external library:

```
$ cat ~/work/a/main.go

package main
import (
        "fmt"
        "github.com/joe/b"

)

func main() {
        fmt.Printf("Hello from joe/a!\n")
        b.Message()
        fmt.Printf("IsNotebook: %v\n", gonbui.IsNotebook)
}
```

Now I want `go get` to fetch me the `gonbui` package:

```
$ go get
github.com/joe/a imports
        github.com/joe/b: cannot find module providing package github.com/joe/b
```

It fails, and hence my program doesn't run. Same with `go mod tidy`, which also fails.

Any ideas ?






Howard C. Shaw III

unread,
Jul 11, 2023, 4:21:31 PM7/11/23
to golang-nuts
What directory did you do the go work init in? The setup description reads like you did it in work/a - shouldn't it be in /work? Can you check where your go.work file is? 

Howard C. Shaw III

unread,
Jul 11, 2023, 4:45:21 PM7/11/23
to golang-nuts
Also did you call go work sync? I think that might be what I actually use in place of go mod tidy. Sorry, ToTK has been absorbing my free time, so it has been a while since I worked on the audio project where I used workspaces.


go mod tidy is intended to update the module's self-contained dependencies. It doesn't use the workspace because in general one may work on multiple independently-maintained modules in the same workspace, and if you're preparing an upstream commit you definitely don't want that commit to rely on unpublished local modifications.

go work sync is intended to update the modules within a workspace to reflect the dependencies selected in that workspace. That is probably what you want if you are working on a set of modules that are all maintained as a single unit."

It seems like currently you are basically forced to use 'go work sync' to update dependencies when using workspaces, and not use 'go mod tidy' or a bare 'go get'.

Jan

unread,
Jul 11, 2023, 5:15:51 PM7/11/23
to golang-nuts
Thanks, yes, I had checked out `go work sync`. I still don't understand what it means with "update the modules withing a workspace" though, or what this command does. I wish the documentation was more concrete (which files it changes, who uses those files, or maybe an example). `go help work sync` has a longer description, but I still don't know what it means by "workspace's build list". But I don't use workspaces often, so I may be missing something obvious.

Anyway I tried `go work sync`, and it doesn't seem to do anything in my scenario -- I didn't notice any files changed by it: 

```
$ cd work/a
$ go work sync
$ cat go.work
go 1.20

use (
        .
        /home/janpf/work/b
)
$ cat go.mod
module github.com/joe/a

go 1.20
$ go get
github.com/joe/a imports
        github.com/joe/b: cannot find module providing package github.com/joe/b
$ go version
go version go1.20.5 linux/amd64
```

ps.: ToTK seems dangerous! :)

Howard C. Shaw III

unread,
Jul 11, 2023, 5:54:56 PM7/11/23
to golang-nuts
I'm not suggesting that it would fix go get, but that it replaces it. Add your extra third party reference, then do go work sync and it should download that dependency.

Jan

unread,
Jul 11, 2023, 6:07:48 PM7/11/23
to golang-nuts
I tried exactly that, it doesn't do that ... Am I doing something wrong ?

Notice in the example below the dependency to `github.com/janpfeifer/gonb/gonbui`. The command `go work sync` doesn't do anything. And `go get` still fails with the same error:

```
$ cat main.go

package main
import (
        "fmt"
        "github.com/joe/b"
        "github.com/janpfeifer/gonb/gonbui"
)

func main() {
        fmt.Printf("Hello from joe/a!\n")
        b.Message()
        fmt.Printf("IsNotebook: %v\n", gonbui.IsNotebook)
}
$ cat go.mod
module github.com/joe/a

go 1.20
$ go work sync
$ cat go.mod
module github.com/joe/a

go 1.20
$ cat go.work
go 1.20

use (
        .
        /home/janpf/work/b
)
$ go get
github.com/joe/a imports
        github.com/joe/b: cannot find module providing package github.com/joe/b
```

cheers

Howard C. Shaw III

unread,
Jul 11, 2023, 6:48:57 PM7/11/23
to golang-nuts
Okay, yeah, got home and tried it out, and go work sync is not doing what I thought it was. I had to do 


in a to get it to build and run.

So yeah, if you want to use a bare go get, you have to do replace directives. Blech.

Jan

unread,
Jul 14, 2023, 2:16:52 AM7/14/23
to golang-nuts
Still on the topic, if I have to use `go.mod` replace clauses, what is the point of `go.work` ? Notice replace in `go.work` doesn't work.

Any thoughts if it would be appropriate to create an issue to add workspace support for `go get` ?

cheers

Howard C. Shaw III

unread,
Jul 14, 2023, 1:10:53 PM7/14/23
to golang-nuts
Such an issue is what I linked you to earlier in the thread. So I do not think you need to create a new issue - however, in the comments in that issue one of the devs asks for use cases where go work sync is not sufficient, so you might want to reply to that with your example where go work sync has not been sufficient.


Well, it is actually about go mod tidy, but the discussion mentions go get as well, and is generally about why the other tools ignore go.work and whether this should be changed. So I think it is the appropriate forum for that discussion.

Jan

unread,
Jul 15, 2023, 2:12:37 PM7/15/23
to golang-nuts
Yes, I read through the thread -- but it seemed different (go work sync / go mod tidy). I'll follow up there then.

thanks!


Reply all
Reply to author
Forward
0 new messages