Skip to content

Instantly share code, notes, and snippets.

@jba
Created December 4, 2018 23:06
Show Gist options
  • Save jba/aa37cb95d8420719a470339379a88590 to your computer and use it in GitHub Desktop.
Save jba/aa37cb95d8420719a470339379a88590 to your computer and use it in GitHub Desktop.
API Compatability in Go
26 November 2018
Jonathan Amsterdam
* Goal
Help the developer make an informed choice about how to change the semantic version of their module.
- Incompatible change (major version bump)
- Compatible but visible change (minor version bump)
- No visible change (patch bump)
Most important: is the new code backwards compatible with the old?
From now on, "compatibility" means backwards compatibility.
* What is Compatibility?
- What do we really mean when we say the new version is backwards-compatible with the old?
A better question:
- What do we want compatibility to be for our tool?
We get to pick a workable definition.
Not behavioral compatibility. Has to be something we can compute.
Hence compile-time compatibility.
* Strict Compile-Time Compatibility
- A new version of a package is compatible with the old if every program that compiles with the old version also compiles with the new version.
Clear and sane.
But too restrictive:
- Unkeyed struct literals
- Embedding and shadowing
- Writing the identical type externally
- unsafe.Sizeof and friends
* What we Want
- Allow valuable changes
- Point out incompatibilities
- Avoid noise
- Keep the underlying principles simple
* The Basic Idea
For each exported package-level symbol in the old package:
- If it was removed or changed incompatibly in the new: incompatible
- If the new added an exported symbol: compatible
On the right track, but much is missing.
* Exposure
// pkg
type u1 int
func (u1) M() {}
var V u1
// outside
V.M()
`u1.M` is visible outside the package
* Type Correspondence
Type identity doesn't work. Consider:
// old
type T int
// new
type u int
type T = u
Or what if I rename an exposed but unexported type?
// old
type u1 int
var V u1
// new
type u2 int
var V u2
We need to establish a _correspondence_ between old and new names.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment