It does? Could you please point to a good introduction/summary? I am actually quite interested to see how they manage the ABI compatibility compared to e.g. Swift.
Swift is one of the few AOT compiled languages where they went the extra mile to ensure some kind of ABI compatibility across language versions, Go just did the usual stuff and no guarantees are given.
You can either create a dynamic linked package, that will dynamically link with other Go compiled code (from same toolchain), or expose a C ABI from a Go compiled .so (which may or may not include the runtime as well).
Huh. So it's basically undocumented w.r.t. the actual implementation details, I was mostly interested in how they manage to bolt interfaces onto structs when they're separately compiled: e.g. if libFoo.so has "struct Foo {}" and "func (x Foo) Frob() { ... }" in it, and if libFrob.so has "interface Frobber { func Frob() }", and then they're linked together to the main application, will Foo actually implement Frobber? If yes, how?
Yes, JIT runtimes have an easier time here (and can more easily do feedback based optimizations on access patterns). For AOT you can do LTO / whole program opt and punt on calls to outside libs, plus provide generics style specializable library code that is not AOT compiled.
I submit it's mostly solvable in language design. They're not all lazy of course, but claiming to be very performance-oriented is a half truth as long as you don't have a strong story here.
There is more to it than lazy language designers.