0

I have two separate Go repositories. One contains an application, another a shared library that the application would like to use. Neither are in $GOPATH.

~/projects/
├── myapplication
│   ├── go.mod
│   └── myapplication.go
└── mylibrary
    ├── go.mod
    └── mylibrary.go

mylibrary/go.mod

module example.com/mylibrary

go 1.14

mylibrary/mylibrary.go

package mylibrary

var Message = "Hello, World!"

myapplication/go.mod

module example.com/myapplication

go 1.14

myapplication/myapplication.go

package myapplication

import (
    "fmt"
    "example.com/mylibrary"
)

func main() {
    fmt.Println(mylibrary.Message)
}

I have no reason to believe that the above should work as the application has no way of finding out where the library is. How do I?

I have tried the following with now results.

  • adding ~/projects/mylibrary to GOPATH
  • running go install for mylibrary

Running go build for the application gives:

myapplication $ go build
go: finding module for package example.com/mylibrary
myapplication.go:5:2: cannot find module providing package example.com/mylibrary: unrecognized import path "example.com/mylibrary": reading https://example.com/mylibrary?go-get=1: 404 Not Found

I can see that it is reaching out to example.com to find the repository (understandably). But how can I tell it to look for somewhere locally first?

2 Answers2

1

I have tried the following with now results.

adding ~/projects/mylibrary to GOPATH

Thats is not how GOPATH works. Under GOPATH style builds source code must live below GOPATH/src. You seem to be using modules so fiddling with GOPATH is useless at it is ignored.

running go install for mylibrary

That does basically nothing. Neither on GOPATH nor in Go module style builds. It is 100% useless to make the Go compiler find source code as it installs packages and executables. For Go module style builds even the package installation is practically useless.

What you should do is follow the "How to Write Go code".

For your setup you have to tell module example.com/myapplication where to find module example.com/mylibrary. This is done through a replace directive in myapplications go.mod:

replace example.com/mylibrary => <file-path-to-source-folder>

Dead simple.

Takeaway:

  • You can either do Modules or GOPATH but don't try to mix them.
  • go install is (only) useful to install executables.
  • If a module A wants to use a local version of module B: Tell module A via a replace directive in A's go.mod.
Volker
  • 40,468
  • 7
  • 81
  • 87
0

Found my answer in How to use a module that is outside of "GOPATH" in another module?, which pointed to Can I work entirely outside of VCS on my local filesystem?.

Seems a bit inelegant but it looks like the official way of fixing my example application would be to modify myapplication/go.mod to do a find-and-replace on the library module name, replacing it with a relative file system path.

So to have this example work, myapplication/go.mod would become:

module example.com/myapplication

go 1.14

replace example.com/mylibrary => ../mylibrary