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).
Proposal for Go2: Disallow imports of external packages in library packages
Definition of the term
main packageA package with the name
maincontaining a functionmain(aka aprogram).Definition of the term
library packageA package that is not a
main package.Definition of the term
external packageA
external packageis 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/bazwould be an external package when imported tobar/foobut not be an external package when imported tofoo/barpackage
fmtwould not be an external package since it is part of the standard libraryProposal
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:
foo/bar/baz(a library package)foo/biz(a main package/ a program)foo/bar(a library package)bar/bop(a library package)fmt(a standard library package)According to this proposal the following imports are allowed:
The following would be rejected:
Benefit:
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
foothen depend on a library packagebar?It won't. However a function of
foocan consume an interface that is implemented by some type ofbar.The main package then would import both library packages, passing the required value to
foo.In order for that to work, the developer of
foowould 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
fooandbarchanges 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).