Go modules - use what is checked out

My team are developing 2 modules - sdk & “client”.
the “client” module consumes the sdk. These modules are 100% work in progress and we will expose them only in a few months.

I’m converting them to “go modules” since I want github .com/hashicorp/terraform v0.11.14
In the client module, when I “go mod init” I see

require (
    github .com/repo/sdk-name v0.0.0-<hash>
    github .com/hashicorp/terraform v0.11.14
)

Since I’m still on development and without actual consumers, I simply want to use the sdk module that is currently checked out, so the sdk is just locally on src/github.com/…, but still when I “go build” in the “client” module, it fetches from the actual github.com.

Currently, everything is under $GOPATH/src/… and I just checkout github.com/hashicorp/terraform to version v0.11.14

Any better way of doing this?

You need to use replace keyword in both your “sdk” and “client”. The keyword documentation is here: https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive.

By now, you should operate both your client and sdk outside of GOPATH (as in outside $GOPATH/src). Otherwise, you’re confusing go that you are not using go.mod. That means you no longer need to go get your package module and can work directly with git in your project structuring.

Example

Assuming you have a workspace outside of GOPATH, arrange as such:

myProject
     +-- sdk
     |   +-- sdk01
     |        +--  go.mod
     |        +--  ...
     |   +-- sdk02
     |        +--  go.mod
     |        +--  ...
     +-- client
         +--  go.mod
         +--  ...

Dealing with SDK

If you’re developing the sdk01 within sdk01, the sdk01/go.mod can have the replace keyword as such:

replace url/path/to/sdk01 => ./

// just to show where to add replace
require (
    github.com/repo/sdk-name v0.0.0-<hash>
    github.com/hashicorp/terraform v0.11.14
)

NOTE:
url/path/to/sdk01 should be the same keyword as the import path in your source codes, as in:

import "url/path/to/sdk01/pkgName"

Then you should be able to develop the SDK internally without forcing yourself to release it every single time. What happened is that go will always refer to the sdk01/go.mod location for your sdk1 package.

Dealing with Client

Similarly, for client, you need to replace all the SDK path pointing to the SDK relatively, with its client/go.mod replace keyword as such:

replace (
        url/path/to/sdk01 => ../sdk/sdk1
        url/path/to/sdk02 => ../sdk/sdk2
)

// just to show where to add replace
require (
    github.com/repo/sdk-name v0.0.0-<hash>
    github.com/hashicorp/terraform v0.11.14
    url/path/to/sdk01 v0.0.0
    url/path/to/sdk02 v0.0.0
)

Then, your client will seek out those 2 SDKs locally to build your client binary instead of pulling from the main release URL.

Some Past Learning

There are some important note:

  1. plan out your release procedures beforehand. It’s easy to release the client’s source codes before the SDK, making your customers confused with dependency error.
  2. before git-committing with that replace clause into any of the go.mod, please do test on whether will it throws an error if the replacement target is missing or clone directly from main URL. If memory recalls, it shouldn’t throw an error.
2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.