His anecdote about Google/Amazon using leap smears to solve the problem is telling. I suspect that they were unable to see outside their own bubble to think about how others may be impacted.
> We did what we always do when there's a problem without a clear solution: we waited
The original problem described the issue and the potential consequences very well and the problem didn't change between the initial report and when cloudflare hit it. It was only until a Serious Industrial User (to borrow a term from Xavier @ OCaml) got bit in a very public way that they actually began thinking about what a clear solution would look like.
And this is exactly why the Go designers don't understand language design, and how this ignorance shines through every single place in their language.
Language design is about compromises. There is never a perfect solution, only one that satisfies certain parameters while compromising others. You, the designer, are here to make the tough choice and steer the language in a direction that satisfies your users.
Besides, characterizing their position as "We waited" is very disingenuous. First of all, this is more stalling than waiting, and second, waiting implies they at least acknowledge the problems, which the Go team famously never does. Read how various issues are answered and then summarily closed with smug and condescending tones.
As for acknowledging, well, they have always been very clear about their position. It makes no sense to spend a decade answering the same question over and over with a long and elaborate response which the person asking has already seen and dismissed. I can understand them becoming condescending after a decade of facing people who act with a deliberately obtuse and holier-than-thou attitude.
It's not like they have been lazy - every release of Go has had a large amount of improvements that matter. Working on generics would have meant sacrificing a (probably large) amount of them.
(for the record, I dearly miss generics too!)
Go is great for server-side web applications. The libraries for that are all there and well debugged. Anything else, not so much.
It appeared to me that the golang devs believed so strongly in the superiority of leap second smearing that waiting for everyone to adopt it was better than compromising their API or the implementation of time.Time.
I want to be clear I'm thankful for the effort everyone has put into golang. Making something people care about enough to love or hate is hard. Stewarding a FOSS project can be a very negative thankless experience as well. While I'm being critical above, there are also lots of examples of golang folks, core or otherwise, making really constructive and productive comments and contributions. I don't mean to trivialize that or ignore it.
I couldn't fit any kinds of thank yous into the talk, except for the credit to the overall community in the first few minutes, because I had a lot to say and only 25 minutes. It's possible I should have written an extended blog post that was more than just the talk, but I didn't - the blog post is just the talk, as it says.
If they implemented everything everyone asked for they'd have another screw-up like C++ or Java.
C++ is a whole other animal. The whole system of a Go program is typically very penetrable. You can trace the code down to the bottom of the stdlib or even the compiler builtins in seconds with ease (thanks to the excellent Guru and vim-go). In my experiences of C++, I doubt how many C++ programmers have ever had a look to the implementation of STL or iostream, which is hard to do ergonomically. Although some people occasionally call the opaqueness encapsulation and see it a good practice (which I don't agree). There are lots of cross compilation and static linking problems that don't arise with Go. There is the problem that one C++ code base will look completely different from others because no one in the C++ world follows conventions the way people in the golang world do.
Compared to them Go is a very well thought out and elegant language.
No you don't. But even if I granted that Golang has a bright future (I don't think it does) by any objective measure C++ and Java are more successful than Golang. LOC, number of devs, performance, install base, etc. Pick a measure other than current hype (not even peak hype) and either Java or C++ trounces Golang.
> I've used all three languages.
I have too. I program golang full time and have for 3 years. I'd switch tomorrow to either of the other languages if I could wave a magic wand (and I'm a fair hater of both).
> and runs in a JVM
I desperately miss the JVM (any of the ones I've used). The amount of sophistication and polish in comparison to the Golang runtime is embarrassing. Debugger support, operational sophistication, IDES, tooling, basically everything is better on any of the JVMs I've used in comparison to the golang runtime.
>Java has mile long class hierarchies, massive try-catch blocks, indentation as thick as my neck
And go has ridiculous copy/paste libraries, horrendous concurrency edge cases, terrible error handling, worse third party libraries and no story around packages.
> There are lots of cross compilation and static linking problems that don't arise with Go.
Because dependency management is not possible in golang. It is literally the worst story in any language I've used in 20 years. You have 2 choice in golang half baked vendoring or a monorepo where you have all of your code in one place.
> Compared to them Go is a very well thought out and elegant language
No, compared to them Go is a young language. There aren't any big projects in Golang yet. We shall see if there ever will be. My theory is that either none will ever happen as some other language will be a better choice, or golang will adapt and all the things people claim are benefits (simplicity, default tooling) will go away, crushed under the reality of complex projects being complex.
But interestingly, not one I would choose with which to embark on a project that I expected to require more than 2000 lines of code (as a ballpark scale measurement).
Go seems to be an excellent glue language. It's very suitable for making a tool that does /this/ and only /this/, putting it in a docker container and running 500 of it at once, linking other parts of my stack together.
I would never use it to write a RDMS, because (as someone who has admittedly been following the situation only loosely) the language maintainers don't seem interested in solving other-people problems. They seem to be making a language for them, and I can respect and understand that, but it certainly gives me pause to think about using it for anything big. If I run into a problem that Go can't solve, will it be possible to persuade the language developers to give a shit? Situation unclear.
The attitude of Go community cannot be separated from the patronizing tone of Go maintainers. In fact it stems directly from the people @ Google working on Go. All the bullshit "you don't need that with go"™ comes directly from Pike,Cox and co. It's fine to be opinionated, but just admit these are opinions instead of engaging into the bullshit they engaged in for years when dismissing this or that problem as irrelevant.
Pike said "Go design" is done. Except that a language which design "is done" is a dead one.
As much as people complain about it, explicitly checking errors like this (and checking them all) is almost essential for production quality enterprise code and any code running on mission critical systems (and to most project managers, all systems are mission critical).
And fwiw I still prefer go's style of error checking to languages that implement massive try/catch blocks.
If you were to code just this "happy path" in Go, it would actually be the unhappy path, because you'd have silent errors resulting in indeterminate state (read: horrible bugs to troubleshoot). If you believe programming is mostly about managing all possible state (as I do), then Go's strategy is way too explicit. In Erlang/Elixir/BEAM's case, as soon as state goes off the rails (read: encounters something the programmer didn't anticipate), it's logged and restarted by its supervisor process almost instantly. (and there are of course strategies for repeated restarts)
That doesn't fix the error, and it doesn't imply the program will work correctly.
Defer to pmarrek on what they meant, but to me it's an issue of practical programming.
In a choice between "I will tell you what to do about errors" vs "I will assume you only crash and restart on any error", I've found the later to be far more efficient.
The former generally leads to a rat's nest of never ending error specialization as unexpected or rare stuff bubbles up in UAT or down the road in prod.
Which isn't to say there's a right answer. There's always going to be particular situations where of course you should use one or the other.
But on the whole, as a philosophical default, fail-and-recycle-on-all-errors is a helluva lot easier to spec, code, test, and maintain for me.
The thing is, there will always be the "unknown unknown" bugs, the ones you didn't even think to anticipate, and Erlang/Elixir/BEAM will always win out in a behavior contest on those vs. in Go, because it is built to anticipate any possible error, not just the possibilities you're aware of.
the erlang strategy is to make it possibly to continue from a known good state when the latter happens where chances are it won't happen again. the errors that happen all the time you will encounter early/often enough that you can work out how to handle/fix them
the result of this strategy is you pretty much never write code that handles the unexpected. it turns out that's a lot of code to not have to write
Coroutines seem like something that is more complex to me than generics.
For example what if you screw up and forget to encode that it SHOUDN'T return OK?
you know that many other frameworks also have these safeguards right? Java server frameworks have been doing it forevever. You can code dirty if you want and deal with no issues or you can be error prone. Hell you can do the same thing in go. You can catch panics. It's not pretty but you can definitely do it.
I forgot one can only point out strengths of erlang not problems with humans coding in general. all hail erlang.
As for Erlang's problems, it does have a fair number of warts and special cases, but the biggest of them all is that it's still a niche language. We actually had to dump Erlang for new projects in favor of Go. That may sound ridiculous, but filling positions involving Erlang was next to impossible (even with candidates without any prior knowledge of the language).
You're basically saying "well, it's still subject to logic errors." Well, that's a nonargument, because you can say that about 100% of languages in existence. That is not a criticism you can levy just against BEAM langs. And we were never arguing that BEAM magically takes care of your logic bugs. Just that it seems to handle the "set of all bugs that are not logic bugs" better.
I also apologize for erlang/elixir fans being rabid and insufferable. ;) A lot of us have dealt with many other langs (I spent years on Ruby and other OO langs) and we're enjoying the unexpected (to us) benefits of this new/old world, that's all. Joe Armstrong is basically Einstein AFAIC...
You can wrap all your code in an unchecked exception and never again have to worry about errors. It's bad practice obviously but there are many situations in which you don't care what error occurred but that an error itself occurred.
<>, err = <>
if err != nil { return nil, err }
<>, err = <>
if err != nil { return nil, err }
Is not what software engineers should spend time on, definitely.Not automating ubiquitous trivial propagations with at least explicit "rie <expr>" (rie for "return if error") is a complete engineering fail under any philosophy.
Oh, I have an idea. If ", err" part is missing from lvalue, insert that mantra automagically under #pragma ARIE=on. This workaround will give designers some stats to embrace.
But hey! Your editor can easily boilerplate all that... boilerplate!
I think Go will continue to grow until we finally have metrics that say that coding something in Go might get you fast-running code but will be slower to code and hell to maintain.
That must be because a lot of function calls are followed by:
if err != nil {
return err
}
https://stackoverflow.com/questions/18771569/avoid-checking-...For example, in Java, I can make as many method calls I want inside of a try block, and catch an exception from any one of them in the catch block. In Go, I would need the equivalent of one catch block per method call, in the form of "if err != nil { return err }". Why repeat yourself?
If you want to pass on an error in Go, its easy to do accidentally -- just omit "if err != nil". Both types of exception handling models enable this kind of behavior. If you are going to do it, you might as well not repeat yourself while you are doing it.
Because you can put more meaningful error messages due to the granularity of the checking. This has made debugging things a lot easier at times.
I'm not saying Go's error handling is better than Java's. But I've written some relatively large and complicated projects in Go (like the Linux $SHELL and REPL scripting language I'm currently coding this very moment) and error handling really is the least of the problems I've been having. Sure, Go's idioms do get in my way from time to time. But on balance Go's idioms save me more time than it wastes. Which is why I keep coming back to Go despite having used more than a dozen other languages in anger. But that's my workflow and my personal preference. Others will find the reverse to be true and I wouldn't be complaining that their language should be more like Go.
Frankly I think people waste too much time comparing languages. Just try something and if it doesn't work, move on. Don't assume your personal preference is a benchmark for how all languages should be designed as there will be a million other developers whose personal preference will exactly oppose you.
But in most cases it is unnecessary since you always have the line number and type of exception printed out as part of the stack trace.
There is also the switch case you need to make when catching an error, like tcp connection then dns resolution and so on, you have to know every time any kind of sub errors.
The worst I've seen is people logging the error message but not the exception itself (so losing the stack trace), or causing another exception to be thrown (and losing the stack trace or cause of the original).
if err != nil {
return err
}
So it's more like 7,7 million to 17,6 million (the top fifth "the" is from comments, so it doesn't count)Meanwhile, well-written C code does this the "wrong" way; every external call has to be done like
if (read(fd, buf, len) < 0) {
hopefully remember to free some things;
return NULL;
}
Why do you think explicit error handling is a Pythonic practice?Guess C is done for.
Original (~1970) K&R (~1980) ANSI C (~1990) C99 (~2000) C11 (~2010)
I would not be surprised to see a C22.
Many small quality of life improvements: stdint.h stdbool.h, inline, restrict, allowing variable declaration within the code, snprintf, variadic macros...
Most of those were accessible through compiler extensions but having them in the standard means that you know it'll work everywhere on any compliant implementation.
Linux definitely isn't conservative when it comes to the language, not only does it use modern features of the language but it even relies on GCC extensions and even sometimes on the compiler's optimizer to produce the correct code: https://unix.stackexchange.com/questions/153788/linux-cannot...
I'm not super familiar with CPython but it also doesn't appear to limit itself to C89, see for instance this random file I opened: https://github.com/python/cpython/blob/master/Python/future....
You can see that `const char *feature` is declared in the middle of some code. It also uses "inline" in several places.
They decided to ditch clang/c2 integration work, and are planning to actually fully support C99 and not only what is required by ANSI C++.
https://www.reddit.com/r/cpp/comments/6mqd2e/why_is_msvc_usu...
https://www.reddit.com/r/cpp/comments/6mqd2e/why_is_msvc_usu...
Go gets frequent updates as well.
"Just as we at Google did not at first understand the significance of handling leap second time resets correctly, we did not effectively convey to the broader Go community the significance of handling gradual code migration and repair during large-scale changes."
Our fault, both times.
This post really frustrates me, because the lengthy discussion about identifying problems and implementing solutions is pure BS. Go read the years worth of tickets asking for monotonic time, and see how notable names in the core team responded. Pick any particular issue people commonly have with golang, and you'll likely find a ticket with the same pattern: overt dismissal, with a heavy moralizing tone that you should feel bad for even asking about the issue. It's infuriating that the same people making those comments are now taking credit for the solution, when they had to be dragged into even admitting the issue was legitimate.