Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

At work (Lytics) 100% of our backend code has been in Go since the beginning over 3 years ago, so slide #6 highlights one of the most things with nearly every Go release:

> Changes to the language: None

https://talks.golang.org/2016/state-of-go.slide#6

We generally get our entire stack upgraded to the latest release within 1-3 months with little effort. It wouldn't be much more work to be ready to upgrade on release day, but we haven't found a reason to worry about it.

Go is such a breath of fresh air compared to past Java and Python jobs where production was usually at least a major release version behind the latest and there was extra effort spent getting everyone using the same implementation (Oracle Java v OpenJDK or Ubuntu's Python v CentOS's -- there are differences!).

Conservative releases aren't a must-have for a language, but I do appreciate having one less operational headache to consider.



> Conservative releases aren't a must-have for a language, but I do appreciate having one less operational headache to consider.

Considering the nature of the work, the programming field seems to be particularly rife with "common wisdom" that's not supported by data. This especially goes towards language design. (In the Chris Granger talk that was recently posted here, he noted that programmers who said they "never" used the mouse, only the keyboard, actually used the mouse 50% of the time.)

The reality of the programming field is that it's "almost a field" [1] -- struggling just as much with empiricism as alchemy was before it evolved into the science of chemistry. Language features definitely suffer from the irrationality of the almost-a-field of programming.

Golang seems to be led by good empiricists who are targeting a specific set of use cases for programming in the large.

    [1] - https://news.ycombinator.com/item?id=9812487


Can you speak to why you were behind latest on the JVM? I can think of less than a handful of breaking changes over the last 15 years. I'd say it was more stable than Go.


Issues I've seen with JDK upgrades over the years (that I can think of right now):

* when "enum" keyword was added, if you had a variable named enum you had to rename it.

* If you use any of the sun.* packages you always ask for trouble on major upgrades.

* GC changes over the years can change how your program runs (latency changes, OOM issues). This probably applies to Go as well.


GC changes is a big one in the JVM, but not so much in Go (so far) as Go offers basically no GC tunables.

So while your awesome CMS tweaks from JDK7 become worthless once you switch to G1 on JDK8, with Go all you can do to optimize the GC is to create less garbage to begin with.

Not trying to say one approach is better than the other: Go's approach is operationally simpler but far less sophisticated than the JVM's.


I don't disagree with the simplicity argument, but as it relates to backwards compatibility, we've already had 1 major change to the GC that caused performance differences that needed to be investigated. With Java typically they'd have left the option to use the old GC (again which increases operational complexity) so that in that case the backwards compatibility argument seems to favor Java.


>as Go offers basically no GC tunables.

This isn't actually true, Go has a single tunable: "GOGC" https://golang.org/pkg/runtime/


I consider that "basically no" compared to Java's daunting array of options.


From that list I would only consider the first one.

Using sun.* packages or relying in GC behaviour is a way to make Java code not portable across certified JVMs.

For example I took part in some projects that were married to IBM JVM, because they were relying on its features.


> relying in GC behaviour

You don't really have a choice in the matter. If you're writing high throughput or low latency applications you are dependent on the JVM's GC behavior, period.


Yes, but what I mean is that each JVM has its own list of GC algorithms.

Just as a very basic example, a certified JVM 8 is not required to have G1.

As for high throughput or low latency applications, yeah actually one is dependent on the whole stack, hence why HPFT is already moving into FPGAs.


> If you use any of the sun.* packages you always ask for trouble on major upgrades.

IIRC, that caution about using sun.* packages was mentioned by Sun in docs of early Java versions, like 1.2 / 1.4 etc. Not sure about more recent ones.


While I agree that Java has been one of the most stable and backwards-compatible languages out there (especially compared to things like Scala, which regularly breaks source and binary backwards compat), there are still rough edges. I am not the original poster, but I can speak for why JVM deployments take time on Hadoop (which I work on).

* In order to upgrade the JVM, all the software you run has to work with the new JVM. If there's even one minor library that doesn't work or is suboptimal, you can't cut over. This is not an issue with Go because everything is compiled to an x86_64 binary there, whereas in Java everything is a jar file that must be run under (almost always a single) JVM.

* During a JVM version change, often Oracle removes or modifies non-public APIs that you need to achieve acceptable performance. For example, there is still no public way to free a DirectByteBuffer or create a FileChannel from a FileDescriptor, so you have to use the non-public APIs. Go almost never has this sort of problem since they tend to provide public APIs for everything you need, including platform-specific things.

* We run really big JVM heaps (>100 GB), and so minor changes in the GC behavior or default settings can cause major issues. For example, JDK8 changed the defaults for many GC tunables. It takes weeks of work at least for us to validate that there are no significant regressions. This is an issue that I would expect Go to have as well since they are changing the GC.

* Enterprise customers are extremely risk-averse, and they're not enthusiastic about deploying a new JVM. Operationally, they don't see any upside, only downsides. Of course JVM upgrades have to happen eventually, but they usually happen when new software is rolling out as well. Oracle's decision to stop shipping security updates for older JVM versions has "helped" in a sense by making the issue seem more urgent.

* Open source projects don't like dropping support for users running older software. There is usually someone around to argue against dropping support for anything that rolled out within the last 5 years.


The first issue is surely an issue with Go as well, if they ever do change the language or std lib in a way that isn't perfectly bug-for-bug compatible? As to upgrade Go I thought you have to recompile everything including all dependencies (I guess there's no stabilised ABI?), so it amounts to the same thing: if one of your dependencies doesn't play nice with the new Go, you can't upgrade.

The private APIs thing is indeed one of the most common issues, along with needed upgrades to bytecode rewriting libraries.


The difference is that you can upgrade each Go application to Go 1.6 separately, whereas with Java, once you upgrade the JVM, all of your applications get upgraded at once. While you could technically have two different JVMs installed side-by-side, in practice nobody actually does this because of the operational complexity and the way that Java handles dependencies. Perhaps this will become an issue for Go if people start using the new shared library feature. For Java, _everything_ is a shared library (sort of), so this is an omnipresent issue.

I think both Go and Java have been good about avoiding backwards incompatible changes in the standard library. Both languages have an explicit policy of avoiding these whenever it is at all possible.

Frankly, the Go standard library is a lot better written than the Java one. For example, I dare you to figure out how to call statvfs from Java, or figure out how many hardlinks there are to a specific file inode. Or make an asynchronous DNS lookup. Even simple things like creating a socket without doing a DNS lookup are very difficult to achieve in the Java standard library.


I really don't get this at all. The JVM is a program. It sits in a single directory. I routinely have several installed on my laptop. There are no operational complexities from having multiple different versions installed, if you want that.

I suspect this really boils down to operational complexities of Linux distros, not Java. If your package manager only lets you install one JVM then maybe this seems "complicated" relative to Go, but that's not a Java problem.

WRT the standard library, yes the Java standard library doesn't expose UNIX specific syscalls. It exposes stuff at a higher level instead because it tries to be portable. That's a different tradeoff to what Go makes but I wouldn't say that makes it badly written. To me badly written would mean buggy, confusingly designed, too small or too big etc. If you want to write non-portable software then that means you may have to link in an extra library or so (like JNA).

Creating sockets does not do DNS lookups in Java. You may be thinking of the URL class, which does, and there's a URI class that avoids that.


It's not a Linux issue. People almost always install the Oracle JVM themselves rather than using a package manager (it's a long story...)

The desire for a single JVM comes partly from the architecture of Hadoop itself. Hadoop is structured as a framework (you give your MR job to YARN and it runs it by creating new JVMs for you).

The Java standard library is weak in many areas. The "write once, run anywhere" ideology is part of it, but there are also just... weak parts.


Actually we have deployments where the JRE is packaged alongside the application, because in some customers teams have the freedom to choose their JDKs.

However we also have projects where the Java version is married to whatever the Websphere deployment of the day supports.

And on Android, well there is no upgrade at all. Which is yet another reason to use the NDK, even with all the 3rd class developer treatment, at least the C++ compiler gets updated and doesn't depend on the Android version of the target devices.


> This is not an issue with Go because everything is compiled to an x86_64 binary there

I don't think the situation is all that different. All the Java code ends up being binary as well, at least after running a while.

At the moment, I think most people's Go projects simply have fewer dependencies. If you poke about on some of the popular Go projects, you'll see some of the bad coding practices that will result in upgrade breakages like checking for exact error strings (unfortunately needed sometimes, I know), so I foresee the same issues over time.


The biggest issue I've seen with JDK upgrades is not the language changes but bytecode changes. Many tools and frameworks such as Guice, Spring, PowerMock, AspectJ, and code coverage tools all operate on byte code, not source code. Therefore, whenever there is a classfile format change, all these tools potentially break until they are updated.


One aspect is that upgrading Go only requires upgrading it on the build infrastructure rather than a deployment of a new JVM. The "next build" will simply be a binary built with a new compiler version.


Hm, it's been over 2 years, so I don't remember many details. I do remember having a couple projects (Kafka, maybe more?) using Scala which required specific JDK versions. Also some databases would recommend certain JDK versions.

So that means you either run different JDKs for different services or you stick with the lowest common denominator.


Perhaps they were using some non-Sun/Oracle programming software besides Java, something like Groovy.


This is my experience as well. The only thing that somewhat breaks between Go project is vendoring (or lack thereof). But in comparison to the pain of supporting python applications that must run on everything from 2.6.6 to 3.5, Go is a walk in the park.


Python is entirely different; the two languages cannot be compared with regards to backwards compatibility.

Python has been around since the early 90s, while Go was conceived very recently. Sooner or later, the quirks that resulted from designing the language so long ago had to be addressed, and that's why there's Python 3. The same can be seen in Java and Ruby.

Once Go is used actively for ~9 years (Python 2.0 to 3.0) and suffers no changes that break backwards compatibility, we can compare it with Python.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: