7 ms·
Their previous blog post (linked in the first sentence) about why the switch from Go to Rust is insightful. I'm currently learning Go but have had my eye on Ru
by horeszko 3y ago
Their previous blog post (linked in the first sentence) about why the switch from Go to Rust is insightful.
I'm currently learning Go but have had my eye on Rust as well and have been wondering about the strengths and weaknesses of each language and how they compare and where each language is best applied.
The linked blog confirms my first impression that Go is well suited for networking applications and simplicity whereas Rust is well suited for OS/low-level applications.
Does anyone here have any experience using Go and Rust? What are your thoughts on the two languages?
- mcqueenjordan 3y agoYes, experience in both. I'm considerably more inclined to use Rust for any use case, but I'll freely admit that I'm biased because it appeals to my sensibilities more. IMO the most compelling use case to use Go over Rust is if you're writing a networked service or networking code.
- sophacles 3y agoHaving used both Go and Rust for networked and networking code, I'd say it's a pretty nuanced set of tradeoffs between the two. I've written a couple protocol handlers in rust (that is parse the packet and handle the logic before giving the data to some other bit of code) and I found Rust really nice for that - real enums, pattern matching, and the use of traits can make interacting with binary protocols (particularly of the state machine variety) really nice with ergonomic interfaces. Meanwhile go's net/IP type (etc) often leave me frustrated. On the other hand, goroutines and channels are such a nice way to handle a lot of message passing around a server application that I find myself reaching for mpsc channels and using tokio tasks like clunkier goroutines in rust often. I think I'd draw the line more along "how often I need to work with byte arrays that I want to turn into semantic types" - if I'm going down to the protocol level and not doing a ton of high level logic I'll reach for rust, if it's more high level handling of requests/responses (http for example) I'll often reach for go. (like the parent, I'm more inclined to reach for Rust over go if all else is equal, but I enjoy go too).
- mcqueenjordan 3y agoTotally agree with this nuance. Really depends on what layer you’re working at.
- phamilton 3y ago> find myself reaching for mpsc channels and using tokio tasks like clunkier goroutines in rust often My experience so far with mpsc/tokio tasks is that Fearless Concurrency TM is pretty solid. There is some clunkiness (mostly inconsistency around async styles), but I've been bit by bad channel usage in golang enough times that rust felt refreshing.
- bluejekyll 3y agoI don’t think comparing Go and Rust is particularly useful. The languages have different goals. I don’t want to start a flame war, but I prefer Rust to Go for a lot of reasons, mainly the lack of runtime, the type system, as well as more compile time safety guarantees.
- ar_lan 3y agoI have no experience with Rust, but have been using Go professionally for ~5 years now. For a lot of the flak that Go gets (and praise that Rust gets), the Go standard library (and supporting ecosystem) indeed is fantastic for anything relating to a web server. When I analyzed Rust around the same time, I noted the Rust standard library [1] did not have HTTP support, and it wasn't a first class consideration. I think Hyper [2] was around, but I've never analyzed it deeply (though based on GitHub stars it seems to be popular). Protobuf [3] is also extremely easy to work with in Go. Given the differences in standard library and applications I see created in both ecosystems, your analysis seems right, though you can probably develop network(ed) applications in both fairly well at this point. [0]: https://pkg.go.dev/std https://pkg.go.dev/std [1]: https://doc.rust-lang.org/std/ https://doc.rust-lang.org/std/ [2]: https://github.com/hyperium/hyper/ https://github.com/hyperium/hyper/ [3]: https://github.com/golang/protobuf https://github.com/golang/protobuf
- juancampa 3y agoThese days Axum is the most common way of building an HTTP server. It sits atop Hyper and it’s very composable thanks to Tower. It supports Websockets out of the box too.
- dgb23 3y agoNot more than a couple of months ago people would recommend actix. There is a lot of enthusiasm and excitement behind the language and the ecosystem reflects that, for better or worse.
- earthling8118 3y agoPeople will still recommend actix. That doesn't mean that axum wouldn't be recommended either. It was there a couple of months ago too and doing extremely well.
- throwaway894345 3y agoYeah, and I genuinely want to like Rust and I pick it up a few times every year (and have done for the last decade), but each time I get burned by trying to do something that would be trivial (and safe!) in Go or C. Most recently, I'm trying to build a non-allocating, minimally copying `Lines` iterator which reads from an internal `Reader` into an internal buffer and then yields slices of the internal buffer on each call to `next` (each slice represents a single line, and it's an error if a line exceeds the capacity of the internal buffer); however, as far as I can tell, this is unworkable without some unsafety because the signature is `fn next(self: &mut Lines<'a>) -> Result<&'a [u8]>` which doesn't work because Rust thinks the mutable reference to self must outlive 'a, and explicitly setting the mutable self reference to 'a violates the trait. If I forego the trait and just make a thing with a `next()` method, then I can't use it in a loop without triggering some multiple mutable borrows error (each loop iteration constitutes a mutable borrow and for some reason these borrows are considered to be concurrent). The only thing I can think to do is have a `scan()` method that finds the next newline and notes its location inside the `Lines` struct and a separate `line()` method that actually fetches the resulting slice from the buffer. I don't run into this in C or Go, and for all of the difficulty of battling the borrow checker, I'm not getting any extra safety (in this case).
- bluefishinit 3y ago> Does anyone here have any experience using Go and Rust? What are your thoughts on the two languages? Rust has a much better type system, Go has a much better standard library. The problems with Rust are that the async solutions are shifting sands and that most people "cheat" by just shoving everything into a Box on the heap instead of properly using lifetimes on the stack. Both of those lead to a lot of inconsistency and sort of defeat the purpose of using Rust in the first place. The main problem with Go is verbose error handling, it may also be too high level for some systems level tasks Rust may be better suited to.
- sophacles 3y agoTheres lots of purposes of using rust in the first place. Some people want the performance. Some people want the safety guarantees and the checking the compiler does for correctness. Some people want the expressive type system (and combined with the above, the ability to encode constraints into data types). I don't think that people who choose based on the third but don't need super tight performance are using it wrong, they just have a different set of priorities than those that are using it for very high performance.
- jerf 3y ago"Their previous blog post (linked in the first sentence) about why the switch from Go to Rust is insightful." I was actually a bit astonished by it. The most trenchant concrete example they could give is... Go's standard library abstraction around file permissions is a bit inconvenient for their use case? This is easily fixed in Go in about a day without a complete rewrite; you just write some new stuff directly against the relevant syscall libraries and use build tags to control the different OS builds. Just because an abstraction exists doesn't mean you have to use it! It is not a requirement of Go that you must use that particular abstraction, it's just something provided by the standard library. We once wrote a library for Perl using the openat and other *at functions because we needed the security guarantees, and it worked fine, despite the "standard library" not working that way. My read is that they're basically doing this because they want to, not because Go forced them to. That's fine. There's nothing wrong with that, if they want to pay the price for migration. (Were someone proposing it to me in real life I'd expect a better reason than "I don't like how it handles file permissions in the standard library", though.) However, as an external observer using it as a grounds to decide it's much weaker than may meet the eye; I wouldn't overprivilege it. The real reason to prefer Rust here would be something on the lines of "We're doing so much crazy concurrent stuff that we need the guarantees that Rust provides via compiler but Go only provides via common practices." The latter can carry you a long ways but it does eventually give out and become insufficient for a codebase, and when that's the case Rust becomes one of the short list of options. "Go common practices" is actually pretty high up on the set of "ways to do reasonable concurrency", reaching above that requires a pretty significant shift to Erlang/Elixir, Haskell, or Rust, and given the goals of the project that would basically leave Rust as the only acceptable performance choice. It's possible that this would qualify for them, though I'm not sure... from what it sounds like they're doing, a task management system that ensures that only one worker is doing a given task and everyone else waits on the relevant output without redoing it would be the core of their architecture, and even if you use that thousands of times per execution that doesn't necessarily mean the code is complex internally.
- returningfory2 3y agoThat article definitely buried the lede. A fair reading of the article is that the only reason they are switching from Go to Rust is because their dev team wants to write in Rust. Which is fine! But I think they could have been more open about that rather than inventing a strange complaint about how Go handles file permissions.
- Mesopropithecus 3y agoDepending on your background, learning either will be beneficial in that you'll learn about a C-like memory model. My experience is that Go is way easier to get started with (both in terms of the language and the libraries). It has a certain concurrency model baked into the language (which in Rust is available in the standard library). It's kind of a lower-level Python. Also I'd say that if you're not familiiar with either language, Go programs are probably easier to read, which can make a difference if you're not working alone on a project. Rust takes a bit more effort to initially get results, but once you get there, you work in a language that gives you expressive ways to create abstraction (this is a matter of taste maybe), generates generally faster code, and does not incur overhead by garbage collection. Also, there are ways to write asynchronous code in an elegant way. The price is that you spend more time learning about structuring programs in a way that the compiler accepts. Once you are past that point, you'll be at least as productive as in Go. I used to dabble with Go and like it, but once I had to write more code, I found it more tedious compared to Rust. But as I said, more readable to the uninitiated, that was one of the Go design goals.
- diarrhea 3y agoRust is also poison for the mind. Sweet, sweet poison. I’m currently back to Python and losing my mind about doing error handling, as well as enforcing correct usage of my library API on the call site. Doing these things well (best?) in Rust is baked into that language’s DNA (Result, Option, newtype pattern, type state pattern, …). It’s painful to go without once you’ve seen the light.
- barelysapient 3y agoUsing Pydantic and the `validate_arguments` decorator can get you a lot more safety. Not as safe as Rust, but more safe than vanilla Python.
- diarrhea 3y agoI love pydantic and use it whenever I can, but that decorator seems a bit misguided, no? It requires type hints anyway, by which point mypy would catch issues with types mismatches statically, before runtime. That would seem strictly more useful. Maybe I’m missing an aspect of what the decorator solves though.
- za3faran 3y ago> Does anyone here have any experience using Go and Rust? What are your thoughts on the two languages? I've worked on an extremely large golang monorepo, but I don't have production Rust experience. They're vastly different languages that they shouldn't really be compared. The only commonality they have is that they both compile to native code, that's about it. Other than that, golang is basically a python/ruby/perl/php competitor, whereas Rust is a C++ competitor.
- didntcheck 3y agoYeah I'm quite confused at how obsessed people are with comparing these two languages specifically. IMO it would make most sense to compare Go to C# or a JVM language. People seem to be thinking that the (good) idea of having it compile to a single executable out of the box means it's in the same class of languages as C, when it's still a managed language - it just bundles the runtime
- masklinn 3y agoIt's a mix of historical happenstance, confusion and historical impression. First, the two languages were initially revealed around the same time, and they were both new AOT-compiled languages targeting a bit downstack from your Java and C#, which was in opposition of the trend since the 90s. Second, Rust was specifically targeted at "system programming" from the start, as from the start Mozilla desired using it to displace C++ in the browser; Go was also initially billed as a "system programming" language, though for a completely different interpretation of the term. Finally, not only did the initial rust announcements very much emphasise concurrency (something Go also does), the initial rust was a much higher-level language, with a mandatory runtime, green threads, and (plans for) a GC. Even though Rust changed drastically between the initial announcement and the 1.0 release, and went significantly downstack (aiming much more squarely at C and C++), those initial impressions have left lasting traces in the global consciousness. And while the two have generally different niches, they very much do compete when it comes to... CLI utilities.
- deleted 3y ago[deleted]
- throwasdfjwe7 3y agoYou should learn both and be able to use both comfortably.
- phamilton 3y agoI have done both. Currently moving a number of microservices from node/ruby/golang to a rust monolith. Slow and steady progress. Our biggest struggle with golang was that our Ruby/FP backgrounds just clashed with golang's style. It wasn't terrible, but we always felt it was more verbose and clunkier to compose and reuse things than we expected. I'm sure generics are making this better, but even with generics the general feel of the type system just felt off to us. Our monolith is http/graphql + postgres in Rust and we like it. Some learning curve for the team, but most of our "application code" is pretty easy Rust and people can jump in and work on it quickly enough. Most work is defining in/out types and implementing a few key traits for them. Our client engineers are comfortable doing it. Our "app infra code" is a little more technical, but we've appreciated the strong type system as we've built out pubsub systems and other important bits of infra. Ultimately though, it's just a culture thing. I'd recommend one of jvm/rust/golang to anyone trying to build apps that handle significant traffic. Which of those 3 is just whichever matches up to your team and their personalities.
- super_flanker 3y agoI have used Go for my day job, I'd say you can get the job done in Go. But the resulting code won't be as elegant as you could do in Rust. I'd chose Rust just because how good the type system is: sum type, pattern matching, iterators, typestate pattern, etc makes programming a pleasure. Navigating async code takes little getting used to though. And be ready for reading many new symbols i.e. ', ~, etc. I've been programming for 12+ years and it gets real boring when you've to type/copy same thing again and again, and Go doesn't want to help you here.