Skip to content

proposal: Go 2: disallow imports of external packages in library packages #25588

Description

@metakeule

Proposal for Go2: Disallow imports of external packages in library packages

Definition of the term main package

A package with the name main containing a function main (aka a program).

Definition of the term library package

A package that is not a main package.

Definition of the term external package

A external package is a library package, that is neither part of the standard library,
nor a package that has the importing package as a subpath.

Examples

  • package foo/bar/baz would be an external package when imported to bar/foo but not be an external package when imported to foo/bar

  • package fmt would not be an external package since it is part of the standard library

Proposal

This proposal would not change the rules for imports of standard packages, it would
not change the rules for imports of subpackages and it would not change the rules for
imports from any main package.

It would only forbid a library package to import an external library.

Examples

We have the following packages:

  • A foo/bar/baz (a library package)
  • B foo/biz (a main package/ a program)
  • C foo/bar (a library package)
  • D bar/bop (a library package)
  • E fmt (a standard library package)

According to this proposal the following imports are allowed:

  • B importing any of A, C, D, E
  • C importing A and E
  • A,B,C,D importing E

The following would be rejected:

  • D importing C or A
  • A importing C or D
  • C importing D

Benefit:

  • No dependencies between external libraries.
  • No references to symbols and functions of an external library in a library package
  • No package management necessary (apart from reproducible builds for main packages).
  • Decoupling, better maintainance
  • Dependencies are owned by the user. May easily be replaced by changing glue code.
  • Leads to larger repos in order to avoid the hassle of lots of glue codes for the users.
  • Larger repos means less dependencies in the main package.

The standard libraries are not affected and since they are released as a whole, there are no package
management issues with them anyway.

But how can a library package foo then depend on a library package bar?

It won't. However a function of foo can consume an interface that is implemented by some type of bar.

The main package then would import both library packages, passing the required value to foo.
In order for that to work, the developer of foo would offer example glue code.

The developer using package foo, copies the example glue code for the integration to his main package.

So what happens, if any of foo and bar changes in an incompatible way?

We assume that the principal functionality offered of bar would not change. If so, it would make sense
to rename it.

However what could change is the exported symbols, the initialization routine etc.

If so, the main package would not compile. Since the glue code is now owned by the developer of
the main package, it can be easily changed without foo having to be updated. In the worst case
one could create a wrapper implementing the needed interface.

In combination with reproducable builds (e.g. vgo) main would not simply stop working without intervention of the user.

UPDATE

After I bit of reasoning, it seems like it would be better to apply this restrictions only if the importing library is "published", where "published" would be defined as having a domain name as part of the package path. These would give some freedom to mono-repos and the standard library (which was excluded anyway).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions