
Proposal: Go 2 transition - piinbinary
https://github.com/golang/proposal/blob/master/design/28221-go2-transitions.md
======
vorg
There seem to be a few standard ways to evolve to the next major version of a
programming language:

(1) Announce the next major version to be far off into the future, and say it
will be as backwards compatible as possible to keep developers supporting the
old version, e.g. Go 1->2.

(2) Build next version to be a little different to current version, provide no
facility for interoperating between versions, then expect developers to switch
over because of the branding, e.g. Python 2->3.

(3) Announce next version to be far off into the future, and say it will be a
totally different language and expect developers to switch because of the
branding, e.g. Perl 5->6.

(4) Don't announce or build a new major version, and keep profiting from
developers using the current version for as long as possible, e.g. Java 1.x.

(5) Announce next version to be very soon, but delay it for as long as
possible with unofficial roadblocks and keep profiting from developers using
the old version for as long as possible, e.g. Apache Groovy 2->3.

~~~
infogulch
(6) Design the new version to be compatible with the old version at the module
level, allowing the different versions to interface with each other, where
individual modules can be upgraded in isolation without breaking changes to
their consumers, e.g. Rust 2018.

~~~
pjmlp
It only works if everyone is obliged to build all their dependencies from
source code, hence why Swift is having such hard time coming up with an ABI
that could survive language evolution.

~~~
testvox
This works on dotnet. The dotnet runtime is versioned separately from the
language so you can use a library written and compiled with C# 5 in a project
that is written in C# 7 so long as they both target a compatible runtime. You
can go even further and use a C# 7 library in a F# or VB project.

~~~
pjmlp
That is because there isn't C#, F#, VB.NET, C++/CLI or any language that you
decide to put on top, just MSIL.

With straight native code, the story is a bit different.

------
Jach
PHP: Good 4->5 transition, they almost made the Python 3 mistake with PHP 6,
but sanely dropped it and the PHP 5 -> 7 seems to be going along nicely...

JS is looking a lot like the C++ story. Totally different language.

~~~
shabbyrobe
The 5 -> 7 transition was great from the point of view of someone writing PHP,
but it was significantly more painful for extension writers. The only way I
could update my stuff was with many hours of careful spelunking through the
PHP source looking for examples of the new APIs, then many more hours of fun
with valgrind working out all of the ZVAL indirection and
zend_parse_parameters changes I'd missed.

I'm fine with the burden of the upgrade being transferred to users of the C
API - that seemed like a very astute trade to me - but the process could've
been made a lot easier with a proper upgrade guide rather than a few hasty,
incomplete notes in the wiki.

------
lazyjones
I like this proposal. For unmaintained code that needs fixing when
incompatible changes are introduced, I wouldn’t make the toolchain
increasingly complex though. It‘d be better to just fork it and have it fixed
by volunteers (or bots!), then put in some canonical location (e.g.
github.com/go2compat/oldhost.org/olddir/...) so developers can just try to
change the include path as a standard solution on such compile errors. This is
more feasible now than 15 years ago since even unmaintained code is usually
public on github or similar. It would help to break as few things as possible
in this case, but that seems to be the intention anyway.

------
AnimalMuppet
The conclusion?

> A real Go 2 would, perhaps unsurprisingly, be harmful.

Nicely done!

------
wwarner
Imma say here that while perl5->perl6 transition didn't work out very well,
the perl4->perl5 transition was hugely successful.

Back to Go!

~~~
setquk
I think that was mostly because Perl pretty much died about the same time.

~~~
ryl00
Reports of perl's death are greatly exaggerated.

~~~
brokencode
It’s fun to use that quote, but is it actually true? At one time, Perl was
extremely popular, and was basically the Python of its era. Now, I barely ever
hear about it, and it mainly seems to be used as a cautionary example of what
can happen to a language when it goes through a major update.

~~~
labster
Yes, it is actually true. Both Perls have a regular release cycle, and
continue to be used in companies around the world. The amount of developers
isn't really growing for Perl 5, but it's not really shrinking either. eBay
isn't dead just because Amazon and Ali became the dominant players, nor is
Perl dead because Python and JS overtook it. The market just got larger.

Also, please try Perl 6. The marketing may be a cautionary example, but the
language itself reflects 15 years of polish.

~~~
setquk
I’m not sure that is the case. I know a lot of Perl developers who jumped
ship. Including me.

While I respect that Perl development is still going, I haven’t seen it used
by anyone in production for at least 15 years.

~~~
theOnliest
We (FastMail) use it in production, and all backend development is in Perl for
all the products. Booking.com, cPanel, Craigslist, and ZipRecruiter all have
sizable Perl codebases, as do many others.

~~~
setquk
As a FastMail customer I use Perl then!

You should have skipped cPanel though from that list. That doesn’t build
credibility ;)

------
Jabbles
I'm not sure how this would work for changes that would affect a whole
program.

For instance, say Go wanted to introduce a moving GC, and say that required
removing interfaces as map keys. How could a function that returned a
map[interface{}]int in one module be called from another that was compiled
with a later version of Go?

Would the whole program would have to be compiled with the non-moving GC?

Perhaps the answer is that Go would never introduce such a change.

~~~
cdoxsey
For this particular case they thought ahead and require implementations to
work with a GC that might move pointers. You run into it with cgo, which, as a
result, has quite arcane rules for passing data between the two:
[https://golang.org/cmd/cgo/#hdr-
Passing_pointers](https://golang.org/cmd/cgo/#hdr-Passing_pointers)

Like with randomizing hashmap keys, they randomly enforce the rule to make
sure that no one relies on it just happening to work since Go's GC doesn't
currently move pointers.

~~~
Jabbles
I don't understand - as you say, cgo requires extra rules. Are you suggesting
that extra rules will apply every time you cross a particular Go version
boundary? This proposal doesn't seem to suggest that.

~~~
cdoxsey
Sorry for the confusion. The rules were put in place to leave open the
possibility of GC which could move pointers. Its not really related to this
proposal directly, but its an example of how you can define a feature in such
a way as to allow future changes.

------
pjmlp
The proposal document seems to be quite good.

------
xte
IMVHO things changes, hopefully for good, so give time and advise far before
etc is a needed and good practice but evolution must happen so if someone have
problem keeping up with reasonable time it means someone do have a problem,
not a thing Go developer can fix or slow evolution because of that.

We all know how bad evolution is in commercial world, force evolution is a
need. Software is not a product, can't last forever untouched.

------
kiallmacinnes
150 comments, and nobody is mentioning the maximum version thing?

Am I alone in thinking that's a terrible idea, that having module authors
around the globe define a maximum version is going to result in masses of
libraries pinned needlessly to old versions, and masses of unmaintained but
otherwise solid and complete libs unpinned, despite them now needing a maximum
version pin?

~~~
ianlancetaylor
Remember that they are only pinned to an old _language_ version. They will
still work fine with new release of Go, they will just be built with the old
language semantics. So what's the harm?

I agree that unmaintained libraries that don't adapt to modules could be a
problem. We'll have to see what happens.

------
throwaway487548
Yes, --lang= or --std= would do the job. Even crosslinking should be easy
since object code is the same.

~~~
bmn__
This is how e.g. C/C++ does it, this design is a mistake. The version
information should be attached to the source code, not the compiler
invocation.

It is pointless to compile source code of a certain version (e.g. C++17) with
the wrong options switch.

------
hiccuphippo
Don't be Perl 6.

~~~
bigdubs
[https://github.com/golang/proposal/blob/master/design/28221-...](https://github.com/golang/proposal/blob/master/design/28221-go2-transitions.md#perl)

~~~
pjc50
Uhoh, they're still proposing to remove features. This is a terrible idea and
crippled both the Perl and Python transitions. If you remove a feature and it
doesn't compile existing programs, it's a new language. The automated
backwards compatibility proposed might help, although it's not clear if you
can mix files and libraries from different versions of the language?

~~~
kstrauser
What did Python remove?

~~~
yammajr
maybe not removed, but they certainly did make breaking changes to the
language. here are some of the most obvious

python 2:

    
    
      print "foo"   # foo
      3 / 5         # 0
      apply         # <built-in function apply>
    

python 3:

    
    
      print "foo"  # SyntaxError: Missing parentheses in call to 'print'
      3 / 5        # 0.6
      apply        # NameError: name 'apply' is not defined

~~~
stcredzero
These are precisely the kind of changes one would make to a language if you
wanted to cause as much pain as possible. (I say this as someone who has been
paid to write a syntax-driven code rewriting tool to go from one language
version to another.)

------
TheDong
I'm surprised there's no reference to rust epochs [0]. Sure, they haven't seen
use in the wild to learn lessons from in that regard, but they're a very well
thought out solution to an effectively identical problem.

They both ended up with very similar results (define a version in
cargo.toml/go.mod, use that version of the language to build), but there's
also more to it than that, and the rust proposal could help guide discussion
of other possible issues too.

[0]: [https://github.com/rust-lang/rfcs/pull/2052](https://github.com/rust-
lang/rfcs/pull/2052)

~~~
Thaxll
I'm not sure it's wise to talk about Rust in those discussions, Rust is the
language that needs nightly for a lot of recent libraries to work... talking
about stability / backward compatibility.

~~~
steveklabnik
Which libraries are you talking about? Empirically, the majority of Rust users
use stable. Additionally, the nightly/stable split exists to serve exactly
this problem; if you need stability, you use stable, and the need for nightly
drops each and every release.

~~~
Thaxll
I think the most popular web framework is rocket.rs, it needs nightly. That's
latest example I have, honestly when I looked a year ago others libraries were
using nightly.

~~~
dx87
Why would you tell people that the recent libraries require nightly, when you
admit that you haven't even looked at the library ecosystem in the past year?
I honestly don't get the motivation that would make you want to come here just
to post lies about a programming language.

~~~
wokwokwok
Hey hey, calm down a little.

I use rust a lot, and it’s been heavily geared towards nightly for a long
time.

The whole rust nightly/beta/stable _hasnt_ worked well, because (afaik) the
beta usage is tiny and people tend to jump on nightly or stable. It’s only
very recently any effort has been made to change this for the new edition.

...so, you know, the comment may not be entirely accurate, sure, but it’s _our
fault_ people have come away from rust feeling that way.

The OP is not at fault here, and definitely not, I think, willfully lying.

Take a deep breath; there’s no need for this sort of attitude, and frankly it
reflects badly on the rest of us (rust users).

~~~
pcwalton
Rust wouldn't be a better language if nightly were instantly made stable.
Instead, we'd have a ton of half-baked features that we'd be supporting for
eternity.

Rocket requiring nightly is unfortunate, and I wish it didn't, but aside from
Rocket stable has been a good forcing function to get crate authors to not add
nightly dependencies.

Anyway, from what I see, actix seems to get more buzz than Rocket these days,
precisely because the former works on stable.

~~~
wokwokwok
True, I’m not arguing that; but, for example, _two days ago_ there was a big
thread about using NLL to solve a problem.

It’s not like we’re past the nightly being the first toy people reach for to
solve problems; that is still very much a thing.

~~~
burntsushi
You're getting pretty far away from the original claim though. Which widely
used crates require nightly to take advantage of nll?

Some crates will always require nightly because there will always be some
people that want to take advantage of the latest features. That's a good thing
to a degree, because it encourages experimentation with said features before
stabilizing them. This is completely different from implying that nightly Rust
is required by a lot of popular crates, which just isn't true. Most people are
productively using stable Rust.

~~~
shadowmint
wasn’t the entire wasm ecosystem on beta until 3 days ago?

/shrug

The OPs point about some/many/[??? numbers of] people not using stable isn’t
that unreasonable imo...

------
ilovecaching
If you're frustrated by the lack of a strong type system in Go then check out
Rust. Rust has type parameters and type constraints that let you write generic
code. The authors have also been super attentive to the good parts of Go. Rust
has great tooling through Cargo, it has rustfmt for formatting, rls for
language server support.

Rust also adds real sum types and a tuple type. Multi-value returns are just
tuples, they aren't a special case of the semantics. Result types let you
avoid writing if err != nil everywhere, but we still believe in the mantra of
not panicking for things that are not truly exceptional.

Rust is also closer to C++s performance, and it's a strongly community driven
project. We also have great concurrency primitives. We have channels, but we
also have futures, which can be scheduled on green threads in a CSP style just
like Go, or can be run behind the Actor model, using async/await syntax with
polling... there's a lot more flexibility there to align the language to your
business needs.

~~~
rhodysurf
So I am a C++ dev by day and I write some go and rust for side projects or
smaller projects at work. Go is SOOOOOO much simpler to write (unless you get
into crazy threading data race stuff) than rust. I like rust (a lot), but the
mental load is a lot more to take on than go.

~~~
steveklabnik
An interesting comparison between experiences is that people describe Rust as
having a lot of mental load at first, but eventually as having way less, since
the compiler does so much for you.

On the topic of the original thread, I wonder why Rust wasn’t included; maybe
it’s because our first release that’s achieving similar goals is happening six
weeks from now, and they wanted to see how things played out in practice, not
in theory.

~~~
Scarbutt
_people describe Rust as having a lot of mental load at first, but eventually
as having way less._

Well that's true for most not-so-semi-trivial stuff one has to learn, it
doesn't mean is always a good idea though.

Just giving a different perspective to beginners.

~~~
steveklabnik
Sure! You should use whatever tools you prefer. Rust isn’t the best
programming language of all times, it has pros and cons like everything else.

------
iofiiiiiiiii
Wow, that is a long piece of text. Can someone TLDR the actual conclusion from
out of that verbosity?

