With Go, all of these problems were basically solved by the strength of the standard library. We could not be happier.
Networking prowess of Go is often underrated in these discussions. Building an web application with server, router, mux, auth etc. all from standard library and just deploying the binary blob on the cloud (irrespective of the architecture) to get your application running with less effort than competing programming languages/frameworks is itself enough for most use cases.
Zero Go-related issues during the whole project. Just drop in one executable and one config file and it just works.
In python you could also implement the API framework, do unit testing, TLS, packaging using standard library. And similarly there are 3rd party frameworks for Go as well.
However, for a lone wolf project, I'd lean more on something like gorm, than just hand-craft and maintain lots of sql.
Another misconception is that it's all for inexperienced programmers. But you need decades of experience to appreciate all the opinionated tradeoffs already made in Go.
It's just one more tool though, and nowhere near FP, which is a different beast altogether. Lots of features around Go and ecosystem is clearly inspired from Haskell. That might be another good tool from the other end of the spectrum.
I used to use Java because it was fast enough, have good libraries and was productive enough. Go is almost as fast, the standard library has most of what you need and its ability to compile to a single binary makes deployments simple.
I also look back and think, could I have done all that in Java? Probably... but I also feel it would have required more effort.
The difference is of course the JIT -- with Go the single binary means you can disassemble it to find out what it's trying to do. JIT adds a layer of mystery.
Also, with Go it's largely possible to avoid heap allocations in performance hotspots. With Java I'm not so sure.
Later
But see below, I think I misconstrued this comment.
To get back to the issue at hand, from my personal experience, if you have many small varibales, your app will perform better in Java than Go. The escape analysis in Java is probably more advanced than the one in Go, and in Java you could also use a generational GC if you prefer throughput to latency.
[1] To be more accurate, the actual optimization the JVM does is called Scalar Replacement, and it's not even about allocating variables on the stack, but rather about inlining primitives: https://shipilev.net/jvm/anatomy-quarks/18-scalar-replacemen...
So even if I can predict how a particular JVM will treat a given jar, I'm still stuck if my code might be deployed across a range of JVMs.
I say all this having written orders of magnitude more Go, with apologies to the Java programmers.
This seems like an odd objection to me. I'm not the biggest Java expert, and I don't currently use it professionally, but I've never written Java that was meant to run on a runtime I not only didn't control but did not know the version of. In theory this was supposed to be a big feature of Java, in practice the community is moving towards bundling the JVM when distributing apps, precisely because versioning is such a fiasco.
I'm obviously surrounded by folks far smarter than me, so I'm posting something probably grossly uninformed to see what the experts think!
I would! That's more or less what I was saying. But earlier on in the life of Java, there were technologies like Web Start and applets that could be embedded in webpages and the idea was that they would run on the client much like JavaScript does today, and you would have little idea of what the client environment was like, other than "it's a JVM." That turned out to be a bad idea for a number of reasons, most famously security, and the situations in which you can't just bundle your JVM are dwindling.
I do think that you are sort of implying that web applets can't determine which jvm they're running under, is this really the case? Was there any reason that the java webapp folks prevented the applet from inquiring of the java version?
This page chats about the version stuff for applets, it seems even with applets there was some options for picking the java version:
https://docs.oracle.com/javase/8/docs/technotes/guides/deplo...
You've made a nice argument for bundling the jvm so maybe I should change my inclination there, especially since I do like avoiding depencencies.
Java applets are basically dead at this point, it’s all JS.
> I do think that you are sort of implying that web applets can't determine which jvm they're running under, is this really the case? Was there any reason that the java webapp folks prevented the applet from inquiring of the java version?
I never wrote applets but the point I was trying to make is that your environment is fundamentally unknown in that context. You could query for different versions and so on, but you would probably never know for sure because you don’t control the runtime environment (everything from the JVM down to the OS). This was supposed to be a big selling point of Java and it has for the most part turned out to be more trouble than it’s worth. That’s all.
I was saying the same thing - albeit poorly perhaps. I'm no Java expert either, but once had to download 'jad' off sourceforge to decompile a buggy 3rd party lib :-).
Modern Java is meant to be packaged with the JVM via jpackage. You will know exactly what you're running on.
The performance measurements I've seen point to Go being faster. To me it seems also to make more sense since Go is compiled to native code, whereas Java still needs JVM to run the non-native binary.
Can you elaborate in what kind of cases Java had better results?
I agree that the lack of generics only shows up once in a while and doesn't hamper productivity as much as might be expected, but I'm still very excited to see them added to the language.
In theory yes, in practice if your Sort array function takes a list of interface{} instead of a well defined type is not going to cause any type bugs. Might be slow, might be ugly, but lack of types on functional/generic stdlib functions doesn't make your code buggier if the original implementation is sound.
If all goes well, we'll get some nice stdlib stuff and 3rd party functions for handling different kind of data with a common api.
But if the - you know what kind of people - discover it in earnest, we'll get a hellscape of C++ templating proportions when people go way overboard with it.
Time will tell.
How do container types, like arrays or hashmaps work without generics? Do you basically have to declare and implement types/methods for each different contained type?
BUT, I need generics all the time indirectly. I've worked in lots of languages over the decades, and I highly value languages with mature/debugged/optimized standard libraries of algorithms and data types (esp. "containers").
Go has an impoverished subset "built-in", and that's all it offers.
One of the best things about Go is the high quality of its standard libraries--where it has standard libraries--so there is a gaping hole where the container and algo libraries ought to be. Experts in these algorithms could take advantage of Go's concurrency for example to write library algorithms that provide a combination of performance and safety that I couldn't create quickly if at all. They could, that is, if they had generics in the language, but they don't, so I'm on my own (for now).
When people (repeatedly) claim that Go doesn't really need generics because they (the claimants) hardly ever need generics, I have to wonder whether their knowledge of DS and algos is especially high or especially low: that they could whip up a debugged and optimized algo as easily as calling it from a library or whether they aren't even aware of the DS/algo that they really ought to be using.
Lots of people find the things you're concerned about missing to not really be the end of the world.
Or you might hate it, and that's also okay.
But those are the only container types with built-in support like that. (Channels can similarly be of any type)
If I remember correctly (haven't used it in a year) Go cheats a bit, and it has few functions in standard library that do have generics (like make), it just doesn't provide this functionality to the developer.
That’s not really true, since built-in containers are special sui generis generics in Go, whereas in an untyped python they get by being untyped, and in python’s statically-checked type system (as implemented in pyright, mypy, etc.) they use general-purpose generics.
At any rate: the person asking the question is wondering how you manage to have performant containers with reasonable interfaces in a language without generics. That's a good question! If you've worked a lot in C, you might be imagining a horrible mess of void-stars or something. But no, the ergonomics are basically those of Python, with extra typing.
I really don't understand how the python comparison makes sense. Since those particular containers are special cased, the ergonomics are also the same as java (and I'd argue more like java than python). Other than ownership, I don't think go's maps are any more python like than C++s or Rusts either.
> reasonable interfaces in a language without generics
and with static typing. Python doesn't fall into that category. It either doesn't have static types, or does have generics. The answer (as others have mentioned) is that go does support generics for a few particular container types.
I’m not making a complaint, I’m pointing out a fact without a value judgement.
> At any rate: the person asking the question is wondering how you manage to have performant containers with reasonable interfaces in a language without generics.
Uh, I don’t see either “performant” or “with reasonable interfaces” there, the question is: “How do container types, like arrays or hashmaps work without generics? Do you basically have to declare and implement types/methods for each different contained type?”
The answer is, for built-in containers, “no, because they use special-purpose generics”. For custom containers, its basically “yes”, but you probably only want a single contained type with an appropriate interface anyway. In neither case is “basically the same as Python” particularly accurate, though I suppose the former case is similar to typed python using generics in the same way as any language with generics would be, while the latter is loosely similar to bare Python or typed Python using protocols instead of generics. But only loosely.
Unless you want to implement utility helpers working on them then it’s yes again, because Go doesn’t have generic functions either, so while it does have a few builtin generic containers, you can’t operate genetically over them.
Go would definitely be my preferred pick for distributed/server applications even though the previous large (mixed C and C++) project I was on was a large distributed application and we did just fine. In fact I'd say our productivity and quality in C++ in that other team was just as good as any I've seen (which is not a random/double blind sort of thing, who knows if that project started in Go from day 1).
I would say that in a large project the language choice has some impact but there are many other variables. A well managed C++ project with competent developers can work well. A less than well managed with so-so developers in Go can be disaster zone. There are lots of other moving pieces, testing, build automation, CI/CD etc.
There are certain areas where I would prefer not to use Go. Basically areas where you spend a lot of time up or down the abstractions. I would prefer not to implement a video codec or a signal processing system in Go. Firmware, motion control etc. would also probably not be a good fit. Going the other direction there are things I can do really quickly in Python (lessay grab some data from some services, do some manipulation, draw some graphs), generally smaller utility like pieces where I want to use data with various random types, use third party libraries. I wouldn't want to write a large project in Python because it's slow and is dynamically typed.
I would also beg to differ wrt/ 10%-20% performance difference. You tend to rely a lot more on GC and produce more "garbage" in Go and the optimizer isn't as good vs. the best C/C++ compilers, I'd say it's more like 50%-150%. But for a lot of stuff it doesn't matter. If you're just making database queries then most of your CPU is sitting there anyways and the delta on the caller side isn't a factor.
Go is pretty nice in it's zone. It's got rough edges but all in all it's fun to use. There are occasional annoyances (like those times where you implement another cache for the 10th time because you can't build a good generic cache or those times where you need a priority queue and interact with those clunky library implementations, so yeah, I'm in the generics fan club). But that hasn't stopped me from using and loving Go. I don't miss those C++ core dumps ;) or dealing with memory management (even with smart pointers and containers it can be a pain). Go's more dynamic aspects (reflection etc.) also make some things easier vs. C++. People can learn Go really quickly which is another bonus, learning C or C++ can take years.
But if you've got a pool of people who have never touched either C++ or Go, I'd pick Go for the project. It's orders of magnitude easier to teach generic programmers the basics of writing decent Go than C++.
On the perf side: I'm curious to know where Go sits now relative to C assuming you elide away all heap allocations in your inner loops. In the early days Go's codegen was based on plan9's simple and simplistic C compiler's back end. Things have gotten much better since then and to my knowledge it's within striking distance of C. But I could be wrong.
number crunching wise, Go is on par with Java and C#: https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
for webdev work, the standard library might not be that fast, but it's fast enough, and if you need even more speed the fasthttp third party Implementation offers good speed: https://www.techempower.com/benchmarks/
Sort of supports my pulled out of thin air numbers (50-150%). In C/C++ you got those lovely SSE intrinsics ;) But look at the binary tree entry as well, that sort of x13 win for C++ really shows you how C++ lets you get sheer power with decent abstractions.
As for XML, it's an absolute bear to encode and decode, documents are often large (dozens, hundreds, even thousands of GB), and the format is complicated enough that writing truly fast parsers is difficult. Being CPU-bound when XML is involved is routine, especially if you need a DOM.
I would pick Go for any large project in a heartbeat.
I have to concur that the haters who post to HN probably have never used this language in earnest.
Here's what you get out of the box:
* Extensive standard library * Cheap concurrency * Fast compilation * Built-in test/benchmark framework, including coverage and race detection * Built-in heap and CPU profiling
Of all the complaints the one I understand the least is the reservations about performance. It is within 10-20% of C, and callouts to C and assembly are possible. (My 8-way multiplexed MD5 routine was written in AVX assembler and lives on in minio.) Extracting that last 10-20% is two or three sigmas away from the norm of how programming languages are used these days.
The objection to generics is similar. The lack of generics shows up -- once in a long while. It doesn't prevent me from being immensely productive with this language.
Looking back at the last few years I've wondered if I could have accomplished what I did in Go by using a different language (C in particular) and the answer, for me, is "not a chance".