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

Switched from Python to Go about 2 years ago. If you need to build performant APIs with a small team there is nothing that comes close. You get the productivity of something like Python with the performance of C++. Or at least very close to it in both cases. (https://getstream.io/blog/switched-python-go/)

The lack of generics hasn't bothered me so far. You just find different solutions to the problem. Composition, interfaces, or if all else fails an empty interface{}. It's rare to really not be able to work around it. It does make it near impossible to build reusable and performant data structures in Go though. (say that you want to build your own heap or list, hashtable etc.) So that's annoying, but something that you rarely run into.

Bigger issue is that GO modules are still not ready for production since the ecosystem didn't catch up: https://github.com/golang/go/issues/24661



You don't get the performance of C++, and it's irresponsible for saying things like that. Any benchmark that's not cherry-picked will show c++ is faster.


Go map vs C++ maps, they pretty much the same for Go 1.9. In Go, once you instantiate a map with a length, you can avoid GC and memory allocs as it grows. https://medium.com/@griffinish/c-and-golang-neck-and-neck-on...


Did you read the article?

>Then of course I remembered that std::map is a red-black tree, i.e. ordered, whereas the Go map is not. Change out std::map for std::unordered_map and C++ pulled ahead, 20% faster than the Go code.


Even that's surprising, since std::unordered_map is notoriously slow (and impossible to optimize given weirdly exposed implementation details in it's API)


So I created a Gist: https://gist.github.com/AshKash/ebf1f70949e76439d6ffed9ccde3...

upped it to 10M ops and used .reserve to avoid unwanted allocs.

Go 1.12 is 2X faster than C++.

This was totally unexpected as I feel the basic algorithms are simple and there is not much you can do to make it faster.

If you have know what is going on, please share.


And Java is 2x faster than golang in this benchmark when I ran it. Many benchmarks are to be taken with a grain of salt.

golang: 7.76 real 8.67 user 0.08 sys

Java: 3.74 real 3.58 user 0.46 sys

    public class Test {
      public static void main(String[] args) {
        final int numOfStrings = 100_000;
        final int numIters  = 1_000;
        var numStrings = new String[numOfStrings];
        for (int i = 0; i < numStrings.length; i++) {
          numStrings[i] = Integer.toString(i);
        }

        for (int i = 0; i < numIters; i++) {
          var strToInt = new java.util.HashMap<String, Integer>(numOfStrings);
          for (final var s : numStrings) {
            strToInt.put(s, s.length());
          }
        }
      }
    }


What's happening is that the std::unordered_map was a mistake. Many parts of it's API prevent implementing it efficiently (For example, every insertion requires allocation, even if you reserve). It's widely regarded, within and outside the standards committee, as a very unfortunate mistake.

swisstable (absl::flat_hash_map) is a popular choice right now for the hash table to use for C++ code that cares about performance. There are other choices as well (dense_hash_map, F14FastMap, etc), But honestly most choices these days are worse than std::unordered_map (well, boost::unordered_map is probably just as bad, since std's implementation was taken wholesale from boost without any thought!)


Did you read the update on Go 1.9? It is on par, I tried the benchmark on my machine why not try it yourself instead of downvoting?


You aren't reading it correctly. The OP was saying it's not fair unless you compare against an unordered map. The update is referring to an ordered map which is much slower than an unordered. The GO math implementation, which is an unordered map, is still significantly slower than the C++ unordered map.


No, it's fairly clear that the update refers to the unordered maps case.


If you're going to compare performance of C++ maps, you may want to consider std::unordered_map, which is a hash map implementation vs std::map's red-black tree.


Not even considering that unordered_map is not the fastest hash map implementation for C++. There is plenty of the flat hash map implementation (swiss tables) around that beats unordered_map by an other factor....

https://abseil.io/blog/20180927-swisstables


Not only consider, but comparing a Go map to C++ absolutely has to do that since go is unordered. A c++ unordered can be significantly faster than ordered in many contexts.


I can't believe the author still published that article even after he realised he was comparing different map data structures.


> You get the productivity of something like Python with the performance of C++. Or at least very close to it in both cases.

s/very close/close enough/

C++ is still multiple times faster in many/most situations [1]. And while it's hard to measure productivity, it's nearly impossible to beat out-of-the-box productivity Python offers [2].

But do people need the performance of C++? Usually not. They just need something faster than Python/Ruby that uses less memory than Java.

And do people need the productivity/prototyping of Python? Often not. Most work is on established code bases where static typing (even weak static typing) is a huge benefit.

Go is full compromises, but in ways that turn out to be very pragmatic.

[1] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

[2] Though if you're making a TCP or HTTP server, Go is pretty great. For a CLI, Python stdlib argparse is unparalleled.


> And do people need the productivity/prototyping of Python? Often not. Most work is on established code bases where static typing (even weak static typing) is a huge benefit.

You can change "productivity/prototyping", remove productivity and just keep prototyping.

Dynamic typing like python has has nothing productive.

Dynamic typing means replacing few minutes to fight against the compilers errors by hours of debugging in runtime/production of problems that could be avoided easily with typing.

That a problem that appears very qickly as soon as you leave the world of "quick and dirty prototype".


> as soon as you leave the world of "quick and dirty prototype".

There's a lot of things though. Want to create a set of charts and graphs of data, especially in a repeatable way? Nothing better than matplotlib.


I have really mixed feelings about Go. 2-3 years ago we went on the train and (re)wrote a bunch of stuff in Go.

We absolutely 100% loved it for small contained pieces like monitoring checks.

When doing a basically boring API with user management some of us found it ok at best, others (like me) really hated it with a passion. Every task that should take 20 minutes and 20 lines of code in any web-first ecosystem (php+symfony, rails, flask) would take 3x as long with 2x as many lines of code, also because of "if err != nil". Sure, a lot of it might have been "Go beginners" but it just never felt smooth for controller-heavy web development.


I use go daily and have come to really like it, however I van completely relate to your pain points. I think there's a lot of confusion over the "go is simple" meme. Go is simple, but it's not easy.

The price one pays for simplicity is the need to discover and master various design patterns; it requires a bit of planning beyond syntax and module exports. It took me quite a bit of time before I felt downright fluent in Go.

I did get there, and I really enjoy the language, but I wasn't immediately productive.


I characterize it this way: Many people who have learned lots of languages are used to having a problem, and then poking through the new language for the feature that solves the problem. Languages designed by and used by these people tend to grow lots and lots of features.

In Go, you are expected to use the features that exist to accomplish the goal, so instead of knowing a ton of features at a somewhat surface level, you need to learn what is there fairly intimately, and use them to their full effect. For a simple example, there's no such thing as "class methods" in Go, so obviously anything best solved via class methods is impossible, right? Except of course it has "class methods". Class methods are just methods that don't reference the instance itself. Go doesn't have any syntactic label for them, but they exist just fine and I make fairly heavy use of them.

Personally, when I read someone complaining that they tried Go and it was "full of boilerplate, repetitive code everywhere and they kept having to copy&paste functions" that they were either A: in the completely wrong domain (see my other comment about how I don't think Go is good for math at all), or B: they didn't do this and were probably trying to jam a map/filter/reduce-heavy workflow, or an inheritance-heavy design, or something else not native to Go, into Go. My code isn't particularly repetitive. Even the error-handling in my mature code tends to be between 1/3-1/2 not "just return the error". (In prototyping it often starts out that way, but by the time I ship something, there's usually a lot more going on.)

As another for instance, you really need to learn to use interfaces to their fullest, as integrated into the type system. You can put methods on anything, even functions or other non-struct types, and anything with methods can conform to an interface. It's really helpful to be able to do that. If you reject all these options as "that's not how I want to design", you're in for a bad time.

Bizarrely, despite their incredible distance on my internal "map of all programming languages", this is one thing Go and Haskell kind of share in common, and something I took from my experiences with Haskell, where you are also handed a certain set of tools and expected to make them work. If you try to take Haskell and force it to be an object-oriented language, you're gonna have a bad time, and you'll complain about how stupid typeclasses are and how stupid immutable data is and how stupid it is that all your code has to be written in IO so why is it even separated out and all kinds of other things. But the solution is to learn how to actually do things the Haskell way, at which point you'll find that while it may not be the best choice for everything, it certainly has some interesting things to say. Go actually does too, around the virtues of structural typing and the privileging of composition over inheritance. It's much less profound than what Haskell has to say, but it's still something.

Neither Go nor Haskell are unique in this characteristic. You really ought to come in to every language you learn with the viewpoint to learning how it does things, rather than coming in and trying to make it be some other language. It's just the simple languages that tend to really put this in your face. The languages with bazillions of features usually have something on offer that looks close enough to what you want that you can force your way through into turning the language into a different language. (And when you ponder what it looks like when you've got a team of 50 people doing that, you start to see some of what Go is designed to fix.)


If I could upvote this twice, I would. You've managed to put words on something I've been struggling to articulate.

Your point about using Go's type system (esp. interfaces) rings particularly true. When I finally figured out how to effectively use the type system, I suddenly found myself writing extremely malleable code. You can move data types and functions around quite freely, and this makes it easy to design & refactor without losing your place.

The flip side, as you say, is that extreme flexibility requires you to build your own skeleton.

BTW, are you github.com/thejerf? If so, I've contributed to Suture, and use it quite often, so thanks for that.


Yes, that's me. I was slow on the draw and missed github.com/jerf .


> If you need to build performant APIs with a small team there is nothing that comes close.

The JVM and .NET think otherwise.


And yet Go pretty much ate the lunch of C# and Java when it comes to backends and devops, despite the fact that both had a decade of head start and generics and large dev teams behind them.

I like C# and Java, certainly much more than C++, but Go hit that sweet spot of little ceremony (try to write a single file Java or C# program), performance, deployability (again, try to deploy a Java or C# program as an Ubuntu service on a low-end 512 MB Digital Ocean host or provide a Java or C# cmd-line program to a Mac user) and programmer productivity.


>And yet Go pretty much ate the lunch of C# and Java when it comes to backends and devops, despite the fact that both had a decade of head start and generics and large dev teams behind them.

This is simply not true. Go is nowhere near that even when only new Greenfield projects are considered. I see many of the start-ups using it but most new projects are still in Java or c#. But go has captured the Dev ops tools area quite a bit.


>Go pretty much ate the lunch of C# and Java when it comes to backends and devops

Are you saying that Go is significantly more popular than Java for backend, server-side development? I'd like to see a citation on that, because pretty much any statistic I've read has said otherwise. If you are saying it's significantly more performant, then I'd like to see evidence for that too.


Benchmarking is error prone, and so are language statistics. Certainly Go has had a meteoric rise and much of the big innovations are happening in Go (Kubernetes, Docker, Prometheus, Terraform).

Go is simple, easy to install, and the benifits of a compiled language are huge. I can apply all of my systems knowledge to understand how my app is performing. The JVM is a career in of itself, and locks you into an ecosystem that is very proprietary and frankly full of lame enterprise salesmen and big business fogies. Go is fun. It’s branding is fun, it’s community is passionate, and a lot of big names are on the tin that speaks to a lot of us who love and grew up on Unix.

I mean, do you want to support Oracle and Larry’s bid to buy more islands or ken and rob?


Compared to passionate comunities, fun and evil CEO arguments, benchmarking and language statistics are not error prone.

You're not really arguing in good faith. This reads more like a parody.


> Benchmarking is error prone, and so are language statistics.

… and so is just saying stuff :-)


I'm running C# on hobby Heroku dynos right now, which are 512MB. I think dotnet core has changed the landscape a bit for C# web services. I made a library which allows me to start a new dotnet project with a vuejs frontend on Heroku within a couple of minutes. I'm really hoping dotnet core continues to see more adoption.


Yep .net core runs comfortably in a minimum 128mb aws lambda. It’s not ultra lean, but there aren’t many use cases I can think of where that matters.


> And yet Go pretty much ate the lunch of C# and Java when it comes to backends and devops, despite the fact that both had a decade of head start and generics and large dev teams behind them.

C# was a windows-only show until very recently with the introduction of.NET Core, and ASP.NET Core is gaining in popularity very fast.

IMHO Go's current adoption rate has more to do with politics and Google's aura than anything else, really.

And I really don't see your assertion on Go eating Java's lunch. Sometimes Java appears to be the only game in town wrt backend development, with Python appearing in second place.

> try to deploy a Java or C# program as an Ubuntu service on a low-end 512 MB Digital Ocean host

I have no idea how a generi C# or Java program fares with so little resources, but I've deployed ASP.NET Core and Spring apps on Hetzner's smallest VMs (2GB) without any problem. I had to google digital ocean's micro VMs to check if such a thing really existed, and I have to say that the price difference (Hetzner's 2GB VM for 3€/month Vs Digital Ocean's 512MB VM for $2.50/month) hardly justifies the trouble.

So unless you're compelled to save about $0.50/month on hosting, I hardly see the point of your example.


Go's big advantage over other memory managed languages is the very low overhead of its runtime - a hello world Go app is probably less than 5MB on disk with all dependencies, and takes up less than 5 MB of RAM. This is absolutely wonderful if you want an architecture of many independent containerized apps, especially with something like Kubernetes or Docker Swarm. Compared to that, the smallest Java container on the classic Docker repos is about 90MB in size and takes up a few tens of MB RAM.

Apparently there is a new Java project [1] floating around that is promising a way to use Java exactly in this use case, but I haven't played around with it.

[1]: https://quarkus.io/


http://august.nagro.us/small-java.html

You can run an empty Spring Boot service in 15MB of RAM or so.


How many mbs for a hello world in forth ?


Hey, I said 'over other memory managed languages'! I really wouldn't compare it to one of the tiniest languages this side of asm. I also think Forth would be a harder sell in a corporation than Go. Or C++. Or ASM, probably.


> try to deploy a Java or C# program as an Ubuntu service on a low-end 512 MB Digital Ocean host

Others have already pointed out doing this with .NET, and yes, it's also possible in Java land. I have done this, even running a Spring Boot service which is generally considered more heavy weight than other frameworks like Dropwizard. A plain Spring Boot service runs in about 15-20MB RAM if I recall. And now with the GC improvements in Java 11+, it's even better.

http://august.nagro.us/small-java.html


You can write csx files since 2015 probably, so it has been really easy for the last 4 years. In F# we are speaking of more than a decade, before go even existed. On the JVM you could have used groovy for even longer than that. For the rest of the points I guess that you never heard about .Net core. And I’m quite curious about the reason that you are unable to install the JRE on Linux, that is something that has been possible for at least two decades and with much, much less RAM than 512MB.


On the JVM, Beanshell has been around since the late 1990's so that's also over 2 decades. In fact, Apache Groovy was pretty much a clone of Beanshell, but with closures added, in its day.


Well yeah, Google uses Go, so clearly it must be the best technology out there! Why would a hip startup use crusty old enterprise technology like Java?


Ironically enough, the vast majority of Google's critical services are in Java and C++. I don't work there, but what's golang used for other than some few services here and there?


People have a lot of valid concerns about using a technology owned by Oracle, and the 2000s ended up leaving a bad taste in people’s mouths from the amount of enterprise shilling that went into Java. Now Java is showing it’s age and cross compiling is no longer the problem it once was.


People are not educated enough and should start living in 2019, not 2010. Java (trademark) is owned by Oracle, but implementation is open source, backed by big names.

> Now Java is showing it’s age and cross compiling is no longer the problem it once was.

I see numerous flaws in this sentence. How Java is showing it's age, language wise, comparing to eg. Go? It is fully OO, has generics and recent versions with advanced functional stuff are making Java pretty modern language on (almost) Scala level.

Regarding cross compiling, it is still the problem. If Go gives you 3-4 platforms out of the box, you can't say cross compiling is solved problem; try to work with MIPS or slightly less popular embedded platforms.


Some people would argue that being "fully OO" is indeed a sign of age at this point. :-)


Which would be ignorant, everything has its place. In any case, https://www.youtube.com/watch?v=HSk5fdKbd3o


None of your arguments were objective or technical, and you've missed the fact that the Java is by far the standard in backend development and more importantly is taught in universities.

Honestly, the only ads I see for Go developers are for blockchain projects, which suggest buzzword-driven development.


There are no objective arguments when it comes to programming languages. If people like Brendan Gregg say that benchmarking is difficult and error prone, we don’t stand a chance.

What we do know is that Kubernetes, Docker, Terrafofm, Prometheus, Caddy, et al. have taken off in part because Go is easily accesible and can scale. Go has risen metorically to the top just like Java did, and there are lots of really huge deployments of Go out there. The JVM will always have certain limitations and require it’s users to specialize in JVM tuning and architecture. Many users are also hesitant to support a company like Oracle, and the enterprise shilling that comes with the Java ecosystem.


Things that are difficult and error prone are often worthwhile. Probably why Brendan Gregg has built a career in performance engineering, instead of giving up and say, complaining on HN how hard life is.

And in fact performance itself is a very objective criteria. Either a piece of software is fast enough or it isn't. This doesn't refer only to percieved performance, but also hard performance indicators established in the requirements of a project. Sw dev 101 really.

Furthermore, languages and their implementations can be assigned to different performance personalities, from very fast (e.g C) to slow (e.g. Ruby). Go doesn't belong in the very fast bucket, it's one level below, hanging out with Java, C# and others.

The arguments regarding Oracle are frankly worthless, but if you want to go there, at least Oracle admit they're evil and restrict their evilness to price gouging on their products. They don't pretend to be some force of good while surveilling billions of people through devices, apps and web platforms like Google does.


Kubernetes was prototyped in Java, it only got rewritten in Go, because another team took over.


I think Java is taught in University and has become the Backend development standard because of historic reasons, not because of its technical qualities.


That's not true at all, and misses the whole collection of technical reasons Java became one of most successful anf popular platforms in history, and why it's still being adopted for other applications and platforms, including those controlled by Go's main proponent: Google.

It might be trendy or fashionable to poopoo on Java, but that criticism isn't driven by technical arguments.


Well, there are plenty of other languages that are just as capable as Java, they just came later.

I just feel like I've been lied to in University. Java was presented as the silver bullet in University. "It runs anywhere and models the real world". "In Java, you can't compare apples and oranges!". Turns out you can, if someone implements an AppleOrangeComparator. Great.

I'm just venting at this point, don't mind me.


Most of use learned C++, Java, or Python in school, that doesn't mean it's right or that it has to be a permanent fixture in your life.


Only in Silicon Valley and startups hoping to get acquired by Google.


I can’t really see how you can be as productive as python with go given the huge amount of boilerplate that you need to deal with and the lack of basic constructs that have been common in a lot of modern languages.


> Switched from Python to Go about 2 years ago.

What a strange comment. Python and Go are good at different things and you can use both.


They’re both general purpose languages that put a premium on usability. Except that Go is faster, runs better in multithreaded environments, and is actually simpler to grasp due to a liberal lack of features. I don’t think it’s crazy to conclude that you should replace all your Python with Go when you can have more efficient program and more compile time checks at no additional cost.

I’ve seen plenty of projects switching to mypy and asyncio kicking themselves that they can’t just use something like Go.


I find Python easy to use. I don't think Go is easy to use at all. Boilerplate, boilerplate, boilerplate.

I don't have to write for loops in Python. Go makes me.


Go is not especially friendly when dealing with lots of similar, but different, json though. Lots of boilerplate and overhead (more code) there.


A lot of that isn't so much "Go" as "statically typed language".

I say this not to defend Go, but to encourage anyone creating a JSON-based API to at least test with a statically-typed language. It's too easy in a dynamically-typed language to create a field that is either a number or a list of numbers, but you just boned all the static languages in the process. Unless you know you're only talking internally, and you're never going to change to a static language of any kind, JSON APIs should generally be written in a subset of JSON that is static-friendly.

It's not that crazy of a requirement anyhow; it's not really a great plan in dynamic languages either because it complexifies the code there, too, just not as much. It's a bit of discipline, yeah, but it's good for you even in a purely-dynamic environment.


Do note that Go also heavily uses reflection (from what I recall) for parsing json, so it can be a bit slower than one would expect.


In some ways Go is a litmus test. Do you have a simple, consistent schema? Are you trying to overload the types of fields and making parsing more difficult? I have run into this problem myself, but I realized that Go was pushing me to simplify and make things uniform which actually made my life way easier in the long run.


nice, I'm just going to send mails to the various creators of the JSONs I consume to ask them to change their protocols because it's not simple enough and solve world hunger while I'm at it


Most of my struggles here have been when consuming /existing/ json blobs, specified elsewhere: 3rd parties, other internal services, "versioned" json blobs, and the big one... consuming json structured logging.

So I think we could both be right.


The additional cost is in the inevitable boilerplate that you'll end up writing to handle real world problems. Python let's you extend the language to help with this. Go, by design, doesn't allow you to. There are pros and cons of each. Not once have I felt I could forget Python because Go exists.


> You get the productivity

How do you measure this? By feelz?

Because I've been a programmer and tech lead for 15+ years, and C++ projects are always done faster than PHP ones.

PHP may be "easy", but better programmers with better tools will always win on development speed.


It's just a shame that you could EASILY bolt on basic parametric polymorphism to Go with 0 cost and huge benefit. And it'll never happen.

The power of a universally quantified interface cannot be underestimated!


Never? This is one of the basic proposals in the Go 2 roadmap.


Rob Pike is against the current proposal and clearly states it comes from the community.

https://www.youtube.com/watch?v=RIvL2ONhFBI


the cost of power is chronically underestimated


Exactly - parametric polymorphism doesn't give you power. It in fact only ever makes your types more constrained!

In a theoretical Go:

    func id<A>(a A) A
This only has one terminating, non-panicking valid implementation.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

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

Search: