Hacker News new | ask | show | jobs
by peterevans 3023 days ago
Huge caveat: This article was written in 2012. So do yourself and fellow reader a favor and not argue over content that is now six years-old.

Obviously, Go has not replaced C++ usage. And, these days, I would see Rust as the more likely step from C++.

(Although, I still feel that it remains to be seen whether Rust will make a huge dent there; is memory-safety the killer-app feature that makes people want to use Rust? Do enough people feel that they Need To Use Rust to make it stick? I'm interested to see how that plays out.)

What Go has done, I think, is replaced interpreted language use (PHP, Python, Ruby) in backend code. Which makes sense, to me--those are already GC languages, so you're pretty familiar with the lay of that land. Generics may not make a huge deal for you because there were no generics to use in those other languages. And Go is quite a bit faster than any of the aforementioned interpreted languages.

5 comments

> What Go has done, I think, is replaced interpreted language use (PHP, Python, Ruby) in backend code. Which makes sense, to me--those are already GC languages, so you're pretty familiar with the lay of that land.

One of the less talked about reasons Go is successful at replacing these languages is the devops story - essentially no runtime dependencies.

This can be easily done in C and C++, by static linking. In java, by building custom jars. This is in fact common practice in large companies, for exactly the reason you mention.
It cannot be done as easily with interpreted languages (Python, PHP, Ruby, Node.js), though--and those are precisely the languages from which Go has been stealing users.
Vendoring in your dependencies is definitely not hard in a dynamic language, just for some reason most projects never bother. I doubt it's a significant reason why they've been moving to Go.

I think it's more prosaic reasons, like that's the language their job uses. People who use dynamic languages tend not to think of themselves as specialists in their stack.

> Vendoring in your dependencies is definitely not hard in a dynamic language, just for some reason most projects never bother.

Not to take a side in static-vs-dynamic linking or the language argument, but that is absolutely incorrect. Single-static-binary is a very significant reason for lots of people moving to Go: that, plus a good cross-compilation story make a lot of problems go away.

Vendoring dependencies is hard in general. It's much harder in dynamic languages.

Some evidence/examples:

- Look at how many different ways of packaging things that Python has.

- Ruby, which most people consider to be one of the scripting languages that got vendoring right out of the gate, still struggles with system libraries used to bootstrap the Bundler process on deployment targets.

- Node.js, another one which is considered to have gotten vendoring right out of the gate, has massive problems with its implementation: package assets in node_modules take forever to fetch/inflate deployment times and artifact sizes, and put strain on systems. People argue that the difference between "my node_modules directories have so many files I ran out of inodes" and "my golang binary is really big" is just a difference of degree, but it's a big difference regardless.

- Vendoring/deploying compiled/native dependencies are a massive hassle in dynamic languages as well: better make sure that you compiled those deps in a way compatible with your target system (a big hassle if you are, say, building an old Perl C/XS extension on OSX and targeting Linux for deployment), and make sure they all link correctly once there, and, if they link, hopefully they link with system libraries that don't have behavior differences from wherever you tested the code. And a lot of popular libraries have a native component.

- There's also the problem of dependency resolution. Several dynamic languages have hard-coded system library paths, which means that if your vendoring misses a spot, you might be loading an unexpected version of something, or failing to start. The "just put everything in the system lib path" ignores the reality of multitenant/multi-use systems, and as a whole 'nother piece of expertise.

- The popularity of Docker/containers is largely driven by the fact that they let you "statically link" your whole stack. That demand indicates that some folks, at least, found the vendoring story for dynamic languages difficult.

> People who use dynamic languages tend not to think of themselves as specialists in their stack.

This sounds suspiciously like "if you use $language you're an idiot/inferior". Spare me your arrogance and language elitism, please. There are specialists, generalists, experts, and idiots on every platform ever invented--in very, very similar proportions.

The argument was made from devops perspective. Which means, no GC is a show stopper. So that eliminates C/C++. Heck the whole point of languages like Perl was C/C++ had huge practical limitations as languages when one wants to get work done quickly.

Also Java never really worked in Devops. You need to a lot of ceremony to just open files and do simple regex work. Unfortunately Python went down the same path.

In Go it is straightforward to write some code directly on servers and deploy. Java can't be written without its famed heavy duty IDEs and other tools which need full desktop environment not just bunch of command line tools.
You can use static link in C/C++ although you may find that the DLL you're statically linking tend to dynamically load the underlying DLL anyway that defeats the purpose.

In most C/C++ world, you're better dynamically linking anyway due to most prior to Visual Studio 2012 it would determine the Service Pack/Dependencies of your host operating system and include that into the exe manifest.

Go has replaced C/C++ in some circles.

Go look at most recent go projects. Kubernetes will never have been done in PHP/Python/Ruby. It would have been a Java or C++ project. Same with cockroachDB, Docker, Etcd, Fleet, Lime, InfluxDB, Prometheus, etc.

I think Rust will stick. Until its metaprogramming abilities can match or outpace C++ and be as fast, it won’t replace C++. I do expect it to replace a lot of Java use cases, and perhaps some Go.
> Generics may not make a huge deal for you because there were no generics to use in those other languages.

While this is technically true, in practice it is a good deal easier to create generic data types in those languages because you don't have to switch back and forth between type-world and no-type-world.

Sort of--you get dynamic types, so you can stuff whatever you want into your collections. You can do that in Go, too--just use interface{}. Sadly, that has not quieted the Generics Brigade.

If you used arrays in PHP, or Ruby, or Python, you can get those--with static typing!--in Go, either with slices for sequential arrays, or maps for associative arrays. I think that satisfies the vast majority of collection use-cases that arise in practical applications of those three languages.

(Note: I think generics would be a Good Thing for Go, and I think they'll probably happen at some point. They keep doing user surveys, and the user surveys keep bringing up the lack of generics as one of if not the number-one issue that users would like to see addressed.)

> You can do that in Go, too--just use interface{}.

This is what I mean by switching back and forth between type-world and no-type-world. If you implement a data type this way, I need to convert your no-type-world (interface{}) data to type-world data at some point after it pops out of your library.

> If you used arrays in PHP, or Ruby, or Python, you can get those--with static typing!--in Go, either with slices for sequential arrays, or maps for associative arrays. I think that satisfies the vast majority of collection use-cases that arise in practical applications of those three languages.

You do often (though not always) see "primitive obsession" in those languages, and Go encourages it even more so due to its only generic containers being the primitives provided by the language.

I don't mean to come off as a Go hater at all. I think it takes the pragmatic side of a ton of trade offs. But I do think that results in some weaknesses that people should be aware of.

Can you expand on what you mean by "primitive obsession"?
Here's an article on C2: http://wiki.c2.com/?PrimitiveObsession. There's a bunch more stuff out there too, if you search for it.
> Sort of--you get dynamic types, so you can stuff whatever you want into your collections. You can do that in Go, too--just use interface{}. Sadly, that has not quieted the Generics Brigade.

This argument, made often by the Go team, contradicts other arguments made by the Go team. Generics done like this have no type safety, which is the central reason for Go.

> If you used arrays in PHP, or Ruby, or Python, you can get those--with static typing!--in Go, either with slices for sequential arrays, or maps for associative arrays. I think that satisfies the vast majority of collection use-cases that arise in practical applications of those three languages.

Of course what everybody wants is trees, sorted maps, sets, ... WITH static typing.

> (Note: I think generics would be a Good Thing for Go, and I think they'll probably happen at some point. They keep doing user surveys, and the user surveys keep bringing up the lack of generics as one of if not the number-one issue that users would like to see addressed.)

No they won't. The real issue is that implementing them is pretty difficult in the compiler. Go's compiler is extremely, extremely simplistic, even to the point that it's badly written. It needs a LOT of cleaning up before anyone can reasonably contemplate adding generics.

> Generics done like this have no type safety, which is the central reason for Go.

Type safety is not the central reason for Go.

I couldn't find the initial announcement, but here is one of the very first presentations by Rob Pike:

https://web.stanford.edu/class/ee380/Abstracts/100428-pike-s...

"The target

Go aims to combine the safety and performance of a statically typed compiled language with the expressiveness and convenience of a dynamically typed interpreted language."

I suppose time will tell whether generics are added or not. I'm--not exactly buying your argument that Go's compiler is badly written, or itself the reason that generics can't be added. But god bless ya for having an opinion.
> is memory-safety the killer-app feature that makes people want to use Rust?

There are algebraic types with pattern matching, sane generics, actually good type inference, strong types that will help you declare behavior only once (as in normal vs. modular arithmetic), and a huge push for not having undefined behavior (that is mostly but not completely successful).

Any of those (and yes memory safety) would be enough of a killer feature on my view. There are still some things I dislike in Rust, but compared with C it's a complete no-brainer.