0

I'm making a Go program and have created a module to divide it. Here is my working tree (the minimal directory is in $GOPATH/src/):

  minimal/
  ├── main.go
  └── ui
      ├── go.mod
      ├── go.sum
      └── ui.go

In the ui module I have the following:

package ui

import "github.com/satori/go.uuid"

func SomeFunction() {
    id, err := uuid.NewV4()
    if err == nil {
        print(id.String())
    } else {
        print(err)
    }
}

The main package uses this module as follows

package main

import "minimal/ui"

func main() {
    ui.SomeFunction()
}

Here is the go.mod file:

module minimal/ui

go 1.14

require github.com/satori/go.uuid v1.2.0

When running go build in the main package folder, everything works and the binary is generated. However, when building only the ui module, it gives the following compilation error:

ui$ go build
# minimal/ui
./ui.go:6:10: assignment mismatch: 2 variables but uuid.NewV4 returns 1 values

You can check https://github.com/satori/go.uuid to see that the function returns two values. What has me puzzled is that building the main package works, but the module doesn't. Why is that?

2 Answers2

1

github.com/satori/go.uuid documentation appears to support GOPATH builds. go module builds, however, produce inconsistent results.

Take the simple API usage from it's README.md:

package main
import "github.com/satori/go.uuid"
func main() {
    u, err := uuid.NewV4()
    _, _ = u, err
}

And try to compile it with go modules:

go mod init
go build

go: finding module for package github.com/satori/go.uuid
go: found github.com/satori/go.uuid in github.com/satori/go.uuid v1.2.0

./main.go:6:9: assignment mismatch: 2 variables but uuid.NewV4 returns 1 values

it pulled tagged v1.2.0 and it failed to compile.

So now pull the latest commit:

go get github.com/satori/go.uuid@master

go: github.com/satori/go.uuid master => v1.2.1-0.20181028125025-b2ce2384e17b

Now it compiles:

go build && echo $?
0

So what is happening here?

github.com/satori/go.uuid is tagged with a mature v1 release, so all dot releases should be feature enhancements with no breaking changes. The latest tagged version v1.2.0 returns only one value from uuid.NewV4().

The latest commit (which go modules infers a pseudo dot release version of v1.2.1-0.20181028125025-b2ce2384e17b) has code that matches the README.md.

If this repo ever becomes tagged as v1.2.1 - this would be a breaking change, as it changes the signature of a function published in a previous v1 release. This would be a violation of semver rules.

Conclusion:

The documentation matches a GOPATH (i.e. non-go modules) build. GOPATH builds always pull the latest commit.

From a go modules perspective, while one may be able to coerce a working build, it does not look like it's supported. Yes, the git repo uses semver tags, but there is no go.mod.

I would not trust this package with a go modules build. Perhaps consider using github.com/google/uuid which does.

colm.anseo
  • 19,337
  • 4
  • 43
  • 52
  • I get it, so in summary `go build` does not check dependencies against the same as `go modules` right? – Danolo AlcNom Jun 05 '20 at 12:16
  • Not quite. `GO111MODULE=on go build` forces the old school `GOPATH` type build, which pulls the latest commits for all imports. This is the case even if you have a `go.mod` in your build directory. `go build` (with no `GO111MODULE` env var), if it finds a fresh `go.mod` will use the latest semver tagged commits for your imports - and stores these versions in `go.mod`. Future builds will continue to use these fixed versions, unless you update a package import manually. – colm.anseo Jun 05 '20 at 12:27
  • It's not "inconsistent", it's just old. `master` is [12 commits](https://github.com/satori/go.uuid/releases/tag/v1.2.0) ahead of v1.2.0. And in those changes, the function signature was changed. – Jonathan Hall Jun 05 '20 at 14:51
  • @Flimzy it's just confusing from a `go modules` build perspective. It looks like its supported - with the `semver` tagging - but looking at the code trajectory - the latest commit is a breaking change. – colm.anseo Jun 05 '20 at 16:01
  • It is supported. It's just that `master` hasn't been released yet. – Jonathan Hall Jun 05 '20 at 16:50
  • @Flimzy when `master` is tagged as a release, what would be it's version? `v1.2.1`? `v1.3.0`? whatever it is, it's a breaking change for a `v1.*` type release. – colm.anseo Jun 05 '20 at 17:14
  • @colm.anseo: You have to ask the package author. But considering it represents a changed API, if the author follows semver properly, it would be v2.0.0. – Jonathan Hall Jun 05 '20 at 17:37
1

The uuid package has different versions. In the latest version, function NewV4() returns just one variable but in the previous versions, it returns two variables which one of them is an error.

You create a go.mod file in the subdirectory of your project, So when you compile your project in the main directory, go-compiler uses one version, and in your ui directory it uses another version to compile. You should just edit the version of uuid package in your go.mod file.

alidadar7676
  • 137
  • 6