
Proposals for Go 1.15 - dgellow
https://blog.golang.org/go1.15-proposals
======
gautamcgoel
I really admire the Go team for sticking to their guns and taking their time
before making language changes. Let's avoid another C++.

~~~
mantap
C++ is 35 years old. The problem is that it has 35 years of backwards
compatibility. Go will not avoid this problem by taking time to make changes,
it can only be resolved by being prepared to break backwards compatibility.

~~~
sammorrowdrums
It's quite an amazing feat that C++ has maintained backwards compatibility.

Watching the ~11 years of Python 2 to 3 adoption has been somewhat painful,
and many libraries have had to offer support for both across much of that
time. (And I believe at time of writing Google isn't even 100% ported to 3 yet
- please correct this if I'm wrong).

I couldn't be happier that Python 3 is finally king though, and major projects
like Django are able to go entirely to 3 now.

Breaking changes in languages can be important and good, but they really can
affect adoption of the new version by existing users, which is tough as often
major users hold some sway in the ecosystem.

JavaScript has the no breaking changes problem even worse, because you have to
support (within reason) all major interpreters existing in the wild, and
cannot easily change the code, so "transpiling" has become the normal.

Microsofts support lifetime for IE11 also means this isn't changing soon. Lots
of old browsers in the wild (even though it has improved dramatically over
last few years).

~~~
mantap
It is _much_ easier to do breaking changes in a compiled and statically typed
language, as long as it doesn't use a preprocessor. Because you can do
automatic upgrades. Some Python 3 changes were not fixable by 2to3 which meant
all source needed to be checked manually line by line, vastly increasing the
cost of upgrading. Worse, Python 2 wasn't forward compatible with Python 3 in
many cases, which required libraries like six to get a transition period
through the back door. The whole process was managed horrifically.

~~~
IshKebab
C++ has not maintained backwards compatibility by doing automatic upgrades. I
don't think that would even count.

Backwards compatibility for a language means that old source code still works
_without_ having to update it, even if you can do so automatically.

Also worth pointing out that C++ _has_ broken backwards compatibility in a
very small number of cases, e.g. the `auto` keyword has changed meaning.
Nobody ever used it before so it wasn't a problem in practice.

~~~
mantap
I wasn't giving C++ as an example of a language that maintains backwards
compatibility through breaking changes using source upgrades, I was actually
thinking of Go when I said that. Obviously C++ does have a preprocessor, which
means upgrades cannot be done automatically in general because e.g. how do you
know which macros in an #ifdef are "supposed" to be defined and which are
"supposed" to be undefined etc? Instead they have to maintain backwards
compatibility in the spec.

------
grammarxcore
I've mentioned this before on HN [1]. I strongly hope 1.15 will finally
address the math/big.addMulVVW issues that really slow down RSA computations,
directly affecting PGP and TLS.

[1]
[https://news.ycombinator.com/item?id=21968913](https://news.ycombinator.com/item?id=21968913)

Edit: I screwed up some initialisms.

~~~
nemo1618
Is RSA mandatory for your use case? Both PGP and TLS support ECC, right?

~~~
grammarxcore
You are correct that the specs support ECC. Go's implementation is not
complete (see
[https://godoc.org/golang.org/x/crypto/openpgp/packet](https://godoc.org/golang.org/x/crypto/openpgp/packet)).
More importantly you can't guarantee clients will be able to use ECC. See this
issue (from my initial link):
[https://github.com/golang/go/issues/20058](https://github.com/golang/go/issues/20058)

------
sacado2
Too bad the try proposal didn't make it. It was a good improvement on the
great but too verbose error management system.

~~~
pleasenotry
This proposal by deanveloper is the best I've seen against try. (apologies for
indentation change - not sure why hn can't preserve it)

[https://github.com/golang/go/issues/32437#issuecomment-49893...](https://github.com/golang/go/issues/32437#issuecomment-498932961)

________________________________________________________________

I actually really like this proposal. However, I do have one criticism. The
exit point of functions in Go have always been marked by a return. Panics are
also exit points, however those are catastrophic errors that are typically not
meant to ever be encountered.

Making an exit point of a function that isn't a return, and is meant to be
commonplace, may lead to much less readable code. I had heard about this in a
talk and it is hard to unsee the beauty of how this code is structured:

    
    
      //
        func CopyFile(src, dst string) error {
          r, err := os.Open(src)
          if err != nil {
            return fmt.Errorf("copy %s %s: %v", src, dst, err)
          }
          defer r.Close()
        
          w, err := os.Create(dst)
          if err != nil {
            return fmt.Errorf("copy %s %s: %v", src, dst, err)
          }
        
          if _, err := io.Copy(w, r); err != nil {
            w.Close()
            os.Remove(dst)
            return fmt.Errorf("copy %s %s: %v", src, dst, err)
          }
        
          if err := w.Close(); err != nil {
            os.Remove(dst)
            return fmt.Errorf("copy %s %s: %v", src, dst, err)
          }
        }
      //
    

This code may look like a big mess, and was meant to by the error handling
draft, but let's compare it to the same thing with try.

    
    
      //
        func CopyFile(src, dst string) error {
          defer func() {
             err = fmt.Errorf("copy %s %s: %v", src, dst, err)
          }()
          r, err := try(os.Open(src))
          defer r.Close()
        
          w, err := try(os.Create(dst))
        
          defer w.Close()
          defer os.Remove(dst)
          try(io.Copy(w, r))
          try(w.Close())
        
          return nil
        }
      //
    

You may look at this at first glance and think it looks better, because there
is a lot less repeated code. However, it was very easy to spot all of the
spots that the function returned in the first example. They were all indented
and started with return, followed by a space. This is because of the fact that
all conditional returns must be inside of conditional blocks, thereby being
indented by gofmt standards. return is also, as previously stated, the only
way to leave a function without saying that a catastrophic error occurred. In
the second example, there is only a single return, so it looks like the only
thing that the function ever should return is nil. The last two try calls are
easy to see, but the first two are a bit harder, and would be even harder if
they were nested somewhere, ie something like proc :=
try(os.FindProcess(try(strconv.Atoi(os.Args[1])))).

Returning from a function has seemed to have been a "sacred" thing to do,
which is why I personally think that all exit points of a function should be
marked by return.

~~~
qtplatypus
At first glance I can tell where the code exits. It happens whenever there is
a "return" or a "try".

------
gameface
I thought the whole point of go was to remove extraneous features and provide
a completely minimal programming language. The argument being that all those
extra features are a source of bugs.

Nevertheless, modules and try... it seems like it’s just an effort to add them
all back in again.

Surely if this happens go will be indistinguishable from all the other
languages it was designed to be different from?

~~~
pjmlp
Programming languages are products just like anything else in the software
industry.

Either they adapt or eventually fade away.

Hence why we get this reboot cycles where new languages get introduced as
revolution against the establishment, and a couple of years later are just as
feature rich as the ones they were "fighting" against.

~~~
chooseaname
> Either they adapt or eventually fade away.

The problem is devs are like, "This is a great language! I wish it had all
these other feature from this other language I've been using."

Well, just go use that other language.

~~~
AnimalMuppet
But they want those features _without the complexity_ of the other language.
So "just go use that other language" doesn't satisfy them, either.

But at least your response makes it so that they're whining about _two_
languages, instead of just one...

