This is a little bit off topic, but why is it that Go is always the language that people compare Rust to? As far as I can tell, they made tons of fundamentally opposite design decisions, so it seems to me that they would be about as comparable as Python and C, or Haskell and JavaScript. What is so similar about them that makes them worth comparing?
IMHO: Python/Haskell/JS is a lot more high level than Go. It is not easy to define a Struct, then have an array of it where it is guaranteed that the in memory representation if a continuous block of memory.
Is it possible to have such an array in Go? I thought that garbage collected languages needed to use indirection for all of their objects to do the reference counting thing, so you would have an array of pointers to objects instead of inlining them like rust. Either way, my point was that the languages seem different enough that they would be used to solve different classes of problems, so I'm confused why they are so frequently compared.
https://research.swtch.com/godata
One difference is that GoLang / Rust / C / C++ is often used at the "lowest level" of writing databases / key value stores / distributed systems, whereas Python / Haskell / JS tend to only be used in high level wrappers.
IMO, the answer is history : they both appeared at roughly the same time (2009) and in the early 2010s they were more similar than they are now.
Because they both described themselves as "systems programming" languages -- though they had materially different definitions of the term.
Note, also, that their websites also have nearly identical taglines:
A language empowering everyone to build reliable and efficient software.
An open source programming language that makes it easy to build simple, reliable, and efficient software.
(Emphasis added.)
Agreed. To me, Go is a competitor to in the Java/C# kind of space: pretty normal OOP, libraries included, GC, faster than a Ruby but not as fast as C, etc.
No. Refcounting/tracing/etc. is only needed if pointers are involved. If you are passing values around (by copying or moving), then both pointers and refcounting/GC are unnecessary.
It's another question that traditionally, GC languages don't offer value types (cf. Java) and make all values heap-allocated by default. That's not a must; for example, Go and Swift and C# all have structs (and the latter two have tuples as well), which you can pass around by value.
I wrote quite a few Go projects, honestly I think there are not that many GOtchas. Maybe around 5. Factoring GOtchas in, I think Go is still an order of magnitude easier to learn than Rust / C++.
Learning Rust is an very interesting journey (emphasize: journey) for me. But for casual projects that does not require raw performance, I still prefer Go.
I thought I'd add a somewhat orthogonal reason to use rust: operator overloading. In scientific computing this makes my code fast more readable. The go developers have acknowledged this, but decided that it was better to prevent people from unwisely using operator overloading when it doesn't make sense, at the cost of making mathematical code harder to read and write. They justify this by arguing that go is not a general purpose programming language.
Add others have pointed out, go is simple, and Thurs simplicity came about through intentional tradeoffs.
Anyone else notice how well Go/Rust match Worse is better - Wikipedia on the 'simplicity, correctness, consistency' dimensions ?
Agreed. To me, Go is a competitor to in the Java/C# kind of space: pretty normal OOP, libraries included, GC, faster than a Ruby but not as fast as C, etc.
Go is not OOP. To a significant degree, it is a reaction against the complexity of OOP patterns and calls itself a "procedural" language like C rather than an object-oriented one. It's true that Go is not suited for some of the really close-to-the-metal stuff that Rust excels at, but there is still a huge crossover in their domains of applicability. I think the reason they are often compared comes down to 1) compiling to native code and 2) being systems-oriented with a focus on reliability. This commonality makes Go compete with Rust in a quite a large problem domain (for example Docker is written in Go, but you can easily imagine it being written in Rust). That is certainly not the case for Python and C, per Lionel's remark. Can you imagine any project where the tech lead ends up wracking his brain over whether to run with Python or C? In my current and previous workplaces, the choice was between Rust and Go for building microservices, with a different winner in each case.
Ok, replace that point with the same "just-use-interface{}
/object
; we don't need generics" mistake that Java and C# both made in release 1.
(This leads into one of my biggest disappointments with Go, actually. It would have been an amazing language to compete with Java 1.0 back in the day. The problem is that it came out well over a decade later -- 2012 vs 1996 -- without really seeming to have learned from a bunch of Java's mistakes.)
No, but I can imagine Python or Go easily. It's not obvious that kubernetes, say, needs anything specific about Go, vs just being written in Python or .Net native or ...
(Compare something like container isolation logic in the OS, where C or Rust could be used, but I expect Go couldn't.)
Yeah, pity about that!
100%. In fact I think the syntax similarities with Python make it clear that Google was very much thinking of replacing Python code when they developed the language.
Didn't I mention Docker is written in Go? So I think you might be using the wrong example there!
I was careful about what I said. Assuming wikipedia is correct,
When running on Linux, Docker uses the resource isolation features of the Linux kernel (such as cgroups and kernel namespaces) and a union-capable file system (such as OverlayFS) to allow containers to run within a single Linux instance, avoiding the overhead of starting and maintaining virtual machines.
Or take something like https://www.docker.com/blog/wp-content/uploads/2014/03/docker-execdriver-diagram.png?w=1024&ssl=1 -- where it uses libvirt (written in C) to manage platform virtualization.
So it sounds to me like Docker builds images and tells the kernel or VM management interfaces to run them, but not that it does the "container isolation logic" itself.
If I've understood that wrong, though, please correct me.
Ah I see - yes Go calls into the kernel to leverage those features of the Linux OS. I would assume Rust would do the same if Docker were written in Rust. If you were going to actually write a kernel, then sure, I'd choose Rust every time, though it is possible to write one in Go (there are examples).
Haha, reminds me of all the GOtchas I faced again and again in go since I am less weary of those when writing rust. Unlike @novice, I hit many GOtchas, the issue is I hit the same GOtchas again and again.
I write (broken) go code faster usually, but most of the time I will spend a lot of time debugging and end up being a lot slower than rust to get a correct working software.
I write rust code slow, but usually when it compiles it works unless it's logic error. I do small projects, compilation time slower than 10s is not really an issue as long as cargo check
runs fast, in fact I think slower compilation time can let me spend more time thinking.
So usually getting broken code I can do it faster it go but getting correctly working code I can do it faster in rust. So I still prefer rust in the end since it's more productive.
Interestingly the founder of Docker, Solomon Hykes, has said:
If WASM+WASI existed in 2008, we wouldn't have needed to created Docker. That's how important it is. Webassembly on the server is the future of computing. A standardized system interface was the missing link. Let's hope WASI is up to the task!
https://twitter.com/solomonstre/status/1111004913222324225
Not about Rust in particular but there is a tight Rust WASM situation, e.g. the wasmer run time written in Rust.
another point in favor of rust, in my opinion, having worked with both, is readability. Go fans will often tout this as a virtue of go, but I find rust wins hands down where it matters. Usually, when I hear this says about go, it's in the context of newcomers to the language being able to easily figure out what code does. I'll concede that idiomatic go contains fewer novel syntactic elements than rust. Probably the only unintuitive pieces of go are channels and the multiple forms of for loops.
Rust on the other hand contains a lot of angle brackets, tick marks, closures, implicit returns, trait bounds, and other new ideas that might trip up a newcomer.
But calling go readable on this count is like calling a ransom note readable because the letters are large, blocky, and clear. The actual logic of a function is hidden among the noise of error handling, so that rather than reading a function to see what it does, I feel more like I'm deciphering it. The simplicity of the syntax slows down broader comprehension.
In addition, the two valued return used for error handling in go leaves too much to the imagination. If an error is returned, is the first value meaningless? If there is no error can the first value be nil? Is"not found " represented by nil, nil
our an error type? There's no effective way to signal this with the type system, so you have to rely on possibly absent documentation. I've run into a number of hard to find bugs around this. Including when using go's standard library.
Go's benefits here, again, are mainly for the newcomer, and while I don't want want to downplay the importance off the experience of onboarding new developers, very little of the code you read or write in a language will be as a newcomer.
Interstesting.
Having worked with more languages than I ever wanted to over a few decades I would say I have been a newcomer in almost every project I was involved in.
Rust is the end of the line for me. The last programming language I ever want to learn.
Yes. Edited