Skip to content

proposal: cmd/go: support peer dependencies #63457

@mitar

Description

@mitar

Background

I am the author of the gitlab.com/tozd/go/errors, a modern drop-in replacement for github.com/pkg/errors which enables errors to be annotated with stack traces and structured details. It is a new package with fresh implementation and is not a fork of github.com/pkg/errors, but it does attempt to keep compatibility with it by reusing its API and by supporting reusing stack traces made by github.com/pkg/errors. The latter is important because in large codebases it can happen that both github.com/pkg/errors and gitlab.com/tozd/go/errors are used.

github.com/pkg/errors exposes its stack trace using the following interface:

type stackTracer interface {
        StackTrace() errors.StackTrace
}

errors.StackTrace is a type (underlying type is []uintptr) exported by github.com/pkg/errors. So to be able to access the stack trace, one has to import github.com/pkg/errors to be able to define the interface. To extract the stack trace (just the underlying []uintptr data), I do something (approximately) like:

switch e := err.(type) {
case interface {StackTrace() errors.StackTrace}:
	st := e.StackTrace()
	return *(*[]uintptr)(unsafe.Pointer(&st))
}

github.com/pkg/errors has been archived in 2021 and is not maintained anymore. Because of this people are searching for maintained alternatives. It is not that github.com/pkg/errors has any known security issues, but it does lack newer features (like errors.Join) and in general people seem to not enjoy having an unmaintained dependency. From what I have seen, even to a degree that they blocklist the dependency using linter tools.

The issue

  • People are trying to remove github.com/pkg/errors dependency.
  • gitlab.com/tozd/go/errors might be a good alternative.
  • But gitlab.com/tozd/go/errors also has a dependency on github.com/pkg/errors so that it works better in codebases where github.com/pkg/errors is used as well and can be interoperable with github.com/pkg/errors.

The proposal

NPM has peer dependencies so solve exactly this problem. I think it could be useful for Go as well. The idea would be that a separate list of dependencies is made in go.mod. So you would have direct, indirect, and peer dependencies. And if that peer dependency is satisfied, an automatic build flag would enable, including the file which uses that peer dependency. (I am open to how that build flag format would look like.)

Alternatives

Build tags seems to be one alternative. I could define a build tag one could use to enable/disable checking for github.com/pkg/errors stack trace on errors (and importing the StackTrace symbol). But the issue is that dependency in go.mod still stays which can trick tools into thinking that the package still uses github.com/pkg/errors.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Incoming

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions