Rust VS Go, which language should developers choose in 2023?
Rust VS Go Which language for developers in 2023?
In 2023, we have a thousand reasons to learn Rust.
On August 7th, the Rust Foundation released the results of the 2022 Rust Survey, which showed that the adoption rate of Rust is continuously increasing, with over 90% of respondents stating that they are Rust users; 29.7% of respondents said that most of their coding work in their jobs is done using Rust, a significant increase of 51.8% compared to the previous year.
There is no doubt that Rust, with its excellent memory safety and concurrency performance, is increasingly becoming the focus of developers’ attention. However, it is also hard to ignore Go, a relatively “veteran” contender that has been selected as the Programming Language of the Year.
Go was born in 2009 and initially gained great attention due to its unique concurrency model and powerful performance advantages. It is worth noting that, like Rust, the creator of Go also “hated” C++, and Go is also a dominant language in cloud-native development.
- Coinsbee gift cards collaborate with JD.com to innovate cryptocurre...
- A quick overview of the Ethereum privacy track What are the applica...
- Singapore Stablecoin Regulatory Framework Released Issuers with Cir...
In the Stack Overflow 2022 Developer Survey, when it comes to the question of “love-hate programming languages”, among the 70,000 responses, programmers clearly have a greater preference for Rust, with 86% expressing a liking for Rust, while 64% expressed a liking for Go. Faced with the popularity of Rust, some developers have raised a soul-searching question: Is it still worth learning Go in 2023?
Furthermore, whether to choose Rust or Go has also become a hot topic on Hacker News these days:
A Rust supporter said, “I have been struggling with this choice for a long time. In the end, Rust won. Firstly, I feel that Rust is closer to the things of the LianGuaiscal era, where you can control everything. Secondly, if wasm and related technologies explode, Rust will be a safer choice. Thirdly, we already have Python for rapid development, so it makes sense to choose something more extreme, and Go is somewhat in the middle. Finally, Rust is used in the kernel and highly regarded, so it is unlikely to be eliminated.”
Another developer who holds the opposite opinion said, “I have been doing Go development for almost ten years, but recently I also tried Rust. I think there are some mandatory and misleading preferences for Rust. From my experience in various startups, including the company I am currently in, Go is the best choice for backend development so far! Note that in terms of performance, functionality, or other aspects… these two languages are very, very similar!”
It has to be said that both Go and Rust are excellent programming languages. They are modern, powerful, widely used, and have excellent performance. But it doesn’t make much sense to directly compare which one is better between Go and Rust, because each programming language represents a series of deep trade-offs. Different languages optimize for different needs, so when choosing a language, we should also consider what kind of problems we want to solve with it. So let’s start from the applicable scenarios of Go and Rust and explore the “way” of their designs.
Although Rust and Go have significant differences in syntax and style, they are both first-class tools for building software. Now let’s analyze them in detail.
Similarities between Go and Rust
Rust and Go have many similarities, which is why people often compare them. What are their common goals?
“Rust is a low-level statically typed multi-paradigm programming language that focuses more on safety and performance.” – Gints Dreimanis
“Go is an open-source programming language that makes it easy to build simple, reliable, and efficient software.” – golang.org
Both Go and Rust are modern programming languages that prioritize memory safety. Over the past few decades of the development of old languages like C and C++, we have become acutely aware that one of the core causes of errors and bugs is unsafe/incorrect access to memory.
So Rust and Go each provide different solutions, but their goal is to make memory management smarter and safer, helping developers write correct and highly performant programs.
Fast and Compact Executables
Both of them are compiled languages, which means that programs can be directly translated into executable machine code, allowing programs to be deployed as a single binary file. Unlike interpreted languages like Python and Ruby, we don’t need to distribute interpreters and a large number of libraries/dependencies along with the program. As a direct manifestation of this core advantage, Rust and Go programs often run faster than interpreted languages.
Both have excellent standard libraries and thriving third-party ecosystems, plus strong commercial support and a large user base. Both have been around for many years and will continue to maintain strong momentum in the coming years. Learning Go or Rust is a very reasonable investment of time and energy.
Pragmatic Programming Style
Emphasizing a pragmatic approach If you do prefer a functional programming style, Rust offers more related tool options, which is one area where Rust excels over Go.
Of course, we can argue about what truly constitutes an “object-oriented” language. But to be fair, the kind of object-oriented programming style that C++, Java, or C# users expect does not really exist in Go or Rust.
– Jack Mott
It can adapt to the real needs of large development teams and large code repositories.
For example, C programmers have been debating for years about where to put parentheses and whether to use tabs or spaces for indentation. But Rust and Go have already solved these problems completely by using standard formatting tools (gofmt for Go and rustfmt for Rust). They will automatically rewrite your code in a style that conforms to the specifications.
It’s not that this specific format is so ingenious, but that Rust and Go programmers are more pragmatic and prefer to choose a unified execution standard.
The style of gofmt may not be everyone’s favorite, but gofmt can help everyone.
Another major advantage of these two languages lies in build pipelines. Both of them have excellent, built-in, and high-performance standard build and dependency management tools. This means that programmers don’t have to fight against complex third-party build systems and don’t need to learn a new system every few years.
Early in my career, I used Java and Ruby, so writing Go and Rust code has always been a bit intimidating, and I felt like I couldn’t master it. But when I joined Google and saw services written in Go, I finally breathed a sigh of relief because I found it easy to build and run.
The same goes for Rust. Although I have only done research on small-scale projects, I can see its ease of use. I hope those endlessly configurable build systems become history soon. Isn’t it great that new languages come with their own dedicated build tools that work out of the box?
Rust or Go? Which one to choose?
After discussing so many issues, and considering that both languages are so well-designed and powerful, does this competition really have a result? Or, since both are excellent options, why do people still get angry on social media and write long comments and blog posts like “Only idiots use Rust” or “Go is not even a programming language”?
Some people are just venting their emotions, but this obviously does not help solve practical problems. At least when it comes to which language to use in a project, or which language to rely on to navigate the programming world, shouting loudly obviously does not help make the right choice.
Now let’s return to the discussion of adults and see how Rust and Go have their own advantages and disadvantages under rational analysis.
Go on Rust: Performance
But Rust’s performance is still superior and can even rival C and C++, which are known as industry performance benchmarks. Unlike these traditional languages, Rust also provides mechanisms for memory safety and concurrency safety, while hardly affecting execution speed. Rust also allows developers to build complex abstractions without sacrificing performance at runtime.
By contrast, although Go programs have good performance, their design focus is mainly on development speed (including compilation), rather than execution speed. Go programmers tend to prioritize code clarity and readability, so the running speed may be slightly slower.
The Go compiler does not spend too much time generating the most efficient machine code; it is more concerned with how to compile a large amount of code quickly. Therefore, in runtime benchmark tests, Rust programs often outperform Go programs.
Rust’s runtime performance also has good consistency and predictability because it does not use garbage collection. Go’s garbage collector is highly efficient and optimized to minimize pause time (pause time also becomes shorter with the release of new versions of Go). However, garbage collection always introduces some unpredictability in the behavior of programs, which may be significant or even unacceptable for certain specific applications (such as embedded systems).
Because Rust’s goal is to give programmers complete control over the underlying hardware, Rust programs can be deeply optimized to approach the maximum theoretical performance of the machine. Therefore, Rust becomes the best option in specific application scenarios where execution speed is more important than anything else, such as game programming, operating system kernels, network browser components, and real-time control systems.
If a programming language is too difficult to learn and keeps most people out, its performance is meaningless. Go seems to deliberately differentiate itself from languages like C++ that have increasing complexity: it has minimal syntax, minimal keywords, and even fewer features.
This means that Go is easy to get started with, and once you have a basic understanding, you can use it to write various programs.
Go is indeed very easy to learn. I had heard people mention this before, but I was still surprised at how it could quickly improve work efficiency when I actually used it. Thanks to the Go language, related documentation, and tools, I was able to write interesting and submit-worthy code in just two days.
– Early impressions of Go by a Rust programmer
The key here is the word “simplicity”. Of course, simplicity does not mean it is easy. A small and simple language is definitely easier to learn than a large and complex one. There are not many ways to achieve a certain effect, so high-quality Go code looks almost the same. This also brings another advantage: we can quickly understand what an unfamiliar service is doing.
Although the core of Go is small, its standard library is very powerful. In other words, besides learning Go syntax, we also need to consider the standard library in our learning curve.
On the other hand, transferring functionality from the language to the standard library means that everyone only needs to focus on learning the libraries relevant to their current development needs. In its design, Go also fully considers the needs of large-scale software development and can effectively support large codebases and development teams. In such scenarios, new developers must be able to get up to speed quickly. For this reason, the Go community has always prioritized simplicity, clarity, generality, and directness of programs.
With the use of the Go language, junior developers often find it easier to improve their work efficiency, but intermediate developers find it more difficult to introduce complex abstractions and thus encounter problems. Due to this characteristic, Rust is often less attractive than Go in the field of enterprise software development.
— Loris Cro
Rust supports more complexity than several other programming languages, so its implementation scope is also larger.
Rust, being specifically designed, contains many powerful and useful features that can help programmers accomplish more tasks with less code. For example, Rust’s pattern matching feature allows for the quick and expressive writing of flexible logic:
Expressiveness and rich functionality
So Rust certainly has its own learning curve. But once you overcome that hurdle, the path ahead is smooth.
If you are ready to learn more complex syntax and semantics (as well as a higher threshold for code readability) and exchange it for the highest level of performance, Rust can even compete with C++ and D. — Dave Cheney
Although Rust and Go borrow some features from each other (such as generics), to be fair, Rust has the upper hand in terms of functionality, while Go’s functionality is relatively limited.
Most languages provide some form of support for concurrent programming (i.e., executing multiple operations simultaneously), but Go was designed for this from the ground up. Go does not use operating system threads, but instead provides a lightweight alternative: goroutines. Each goroutine is an independently executing Go function, and the Go scheduler maps them to one of the operating system threads under its control. In other words, the scheduler can efficiently manage a large number of concurrent goroutines using only a limited number of operating system threads.
Therefore, we can run millions of concurrent goroutines in a single program without worrying about serious performance issues. Because of this, Go becomes a complete solution for large-scale concurrent applications such as web servers and microservices.
Go also provides channels for goroutines, which is a fast, safe, and efficient way to implement data communication and sharing. Go’s concurrency design level is indeed high, and the user experience is quite easy and enjoyable.
In general, the design difficulty of concurrent programs is very high, and it is not easy to build reliable and correct concurrent programs in any language. However, due to the consideration of this requirement at the beginning of the project, the concurrency programming mechanism in Go has been made as simple as possible and well integrated.
Go allows us to more easily build an application that can be carefully deconstructed, which can be deployed as a set of microservices and fully leverage concurrency advantages. Rust can also achieve this, but it is more difficult to implement. In a sense, Rust is more suitable for programmers who never allow security vulnerabilities due to memory issues; but correspondingly, they have to put more effort into performing tasks that are relatively simple for other languages (including Go). – Sonya Koptyev
In comparison, the concurrency mechanism in Rust has just landed and is not yet stable, so please continue to pay attention to this active development direction. This also has its advantages, such as the rayon library in Rust, which provides a very elegant and lightweight method to convert sequential computation into parallel computation.
It’s really great to have lightweight syntax for generating goroutines and using channels. This is a direct manifestation of the power of syntax, and various small details make the concurrency programming experience in Go much better than other languages.
– Early impressions of Go by Rust programmers
Although implementing concurrent programs in Rust may not be easy, it is still completely feasible, and these programs can also benefit from Rust’s carefully designed memory safety guarantees. Take the Mutex class in the standard library as an example: in Go, we may forget to acquire a mutex before accessing certain content; but in Rust, we don’t need to worry about it at all.
Go focuses on making concurrency one of the most core concepts. This doesn’t mean that we can’t achieve similar concurrency effects in Rust as in Go, but the implementation difficulty is somewhat challenging for programmers. Go focuses on making concurrency one of the most core concepts. This doesn’t mean that we can’t achieve similar concurrency effects in Rust as in Go, but the implementation difficulty is somewhat challenging for programmers.
– Dave Cheney
As mentioned earlier, both Go and Rust prevent various common programming errors in their own ways, especially those related to memory management. However, Rust goes further and goes all out to ensure that unexpected security vulnerabilities are not introduced.
Rust’s compiler is so strict that it checks every variable we use and every memory address referenced. It avoids potential data race situations and notifies you of undefined behavior. In the world of Rust, concurrency and memory safety issues are almost impossible.
– Why choose Rust?
In other words, the programming experience in Rust is different from almost all other languages, and it can be quite challenging when first getting started. But for many developers, this effort is clearly worth it.
For me, the biggest advantage of Rust is that the compiler has become my good assistant, it will not let any detected bugs slip through (to be honest, sometimes I feel like it has magic).
— Grzegorz Nosek
Many languages, including Go, also provide tools to help programmers avoid errors, but Rust takes this effect to a new level. Many incorrect programs cannot even be compiled.
In Rust, various library tools can help programmers prevent user errors. Rust allows us to specify a piece of data and then ensure that it does not belong to anything else and cannot be tampered with by anything else. I can’t think of any other language that provides so many tools to prevent accidental misuse, and this feeling is wonderful. — Sam Rose
“Fighting with the borrow checker” is a hurdle that newcomers to Rust must pass, but in most cases, the checker is not a real enemy. The problems it finds are indeed real bugs (or at least potential bugs) in the code. It may force us to fundamentally refactor our programs to avoid such problems—if you really consider correctness and reliability as top priorities, then this strict requirement is obviously a good thing.
Looking at it from another perspective, can a new language be called a new language without changing the way of programming? And when using other languages, Rust teaches us the same significance of safety thinking.
If you choose Rust, it is often because of the security design it provides: safety regarding null pointers/data races, predictable runtime behavior, and complete control over hardware. If these things mean nothing to you, then there is really no need to use Rust. After all, there is a cost behind these benefits: it is difficult to get started. You have to get rid of bad habits and master new concepts. At the beginning, everyone will be tormented by the borrow checker.
— Matthias Endler
The actual difficulty of getting started with Rust programming may depend on what other languages you have used before. Python or Ruby programmers may feel that Rust has too many restrictions, but others may find these clear and explicit constraints quite good.
If you are a C or C++ programmer who has spent weeks searching for memory safety bugs in the language, then you will definitely fall in love with Rust. So “fighting with the borrow checker” becomes “can the compiler be used like this? It’s awesome!”
— Grzegorz Nosek
Today’s server programs contain millions of lines of code, written by hundreds or even thousands of programmers, and are updated almost every day. Go has fully considered the need for efficiency improvement in such environments during its design and development. Go’s design considerations include strict dependency management, adaptability of software architecture as the system grows, and robustness across component boundaries. — Rob Pike
When solving problems alone or in small teams, whether to choose a simple language or a rich language is purely a matter of personal preference. However, as the software scale expands, complexity increases, and teams expand, the differences between the two types of languages begin to emerge.
For large-scale applications and distributed systems, the importance of code execution speed is often lower than development speed: languages like Go, which deliberately emphasize streamlined design, can shorten the adaptation time for new developers and enable them to contribute to large codebases more quickly.
Using the Go language, junior developers often find it easier to improve work efficiency, but intermediate developers find it more difficult to introduce complex abstractions and therefore encounter problems. Because of this characteristic, Rust’s appeal in enterprise software development is often not as strong as Go’s.
— Loris Cro
When it comes to large-scale software development, clarity and readability are always more important than clever elegance. The limitations of Go actually make it more suitable for the needs of enterprises and large organizations than more complex and powerful languages like Rust.
Rust vs. Go: Differences
Although Rust and Go are both popular and widely used modern languages, they are not true competitors because they target completely different use cases.
The entire programming approach of Go is completely different from Rust, which is particularly suitable for some people but can also completely enrage others. This is normal because if Rust and Go are both solving the same basic problems in essentially the same way, why do we need two independent languages?
So, can we start by examining the approaches taken by Rust and Go to understand their essence? Let’s try it together below.
The question of “to garbage collect or not to garbage collect” never has a correct answer. Generally speaking, garbage collection and automatic memory management help us develop reliable and efficient programs quickly and easily. So, for some developers, these are essential features.
However, some people believe that garbage collection and the performance overhead and global pauses it brings can make the runtime behavior of programs unpredictable and introduce unacceptable delays. This argument also makes sense.
Go and Rust are two completely different languages. Although both can be described simply as system languages or alternatives to C, their goals, application scenarios, language design styles, and feature priorities are indeed vastly different. Garbage collection is a major core difference. Garbage collection in Go makes the language simpler, smaller, and easier to understand. The lack of garbage collection in Rust makes it extremely fast (which is particularly suitable for developers who not only require high throughput but also low latency), while also achieving a range of features and programming patterns that Go cannot possibly achieve (at least without sacrificing performance).
Closeness to Hardware
The development history of computer programming can be regarded as an increasingly complex abstract development process. It allows programmers to solve problems without paying too much attention to the actual operation of the underlying hardware. This design makes programs easier to write and more portable. However, for some other programs, it is more important to access hardware and precisely control the execution of the program.
The goal of Rust is to allow programmers to be “close to hardware” and regain more control; while Go abstracts away architectural details and allows programmers to be closer to the problem.
These two languages have different application scopes. Go is good at writing microservices and typical “DevOps” tasks, but it is not a system programming language. Rust is more powerful in tasks emphasizing concurrency, security, and/or performance, and its learning curve is indeed steeper than Go’s.
— Matthias Endler
In fact, for most programs, performance is less important than code readability. However, if certain projects do prioritize performance, many design trade-offs in Rust will help push the execution speed of the code to the limit.
In contrast, Go values code simplicity and is even willing to sacrifice some runtime performance for it. But Go’s build speed is unparalleled, which is often more important for large-scale code projects.
If you need top performance, then either of these two languages can be chosen, and the speed performance will definitely not disappoint. Also, if you are building a web service that handles high-intensity loads and requires flexible vertical/horizontal scaling, both languages can meet the requirements.
— Andrew Lader
On the other hand, if we don’t insist on programs never making errors, the trade-offs will be different. Most code does not consider long-term use, but some programs do run in production environments for many years. Faced with these realities, perhaps it is necessary to invest a little extra time to develop and ensure that the program can run correctly and reliably without causing a heavy maintenance burden in the future.
Both Go and Rust can help us write correct programs, but the specific methods are different: Go provides an excellent built-in testing framework, while Rust focuses on eliminating runtime bugs through its borrow checker.
My view is: for code that needs to be released tomorrow, use Go; if it is code that must run reliably within the next five years, then choose Rust.
— Grzegorz Nosek
Although Go and Rust are both capable of supporting serious development projects, it is best to fully understand their various features and advantages. In short, other people’s opinions are not important: only you can decide which programming language is more suitable for your team and project requirements.
If you want to speed up development, for example, if you have many different services to write, or if the development team itself is large in scale, then Go language is definitely the right answer. Go focuses on concurrent design and can quickly pinpoint unsafe memory access behavior (Rust can also do this), but it doesn’t force you to manage every detail one by one.
Go is fast and powerful, but its core highlight is to help developers get out of trouble and focus on simplicity and consistency. On the other hand, if you need to maximize every bit of performance space, then Rust is the ideal choice.
In summary, I hope this article can help everyone understand the highlights of Rust and Go. If possible, it is best for everyone to experience these two languages to some extent, because they are very useful in any technical path, even for amateur programmers.
But if you only have time to seriously study one language, please first understand the specialties and tendencies of Go and Rust before making a choice.
Of course, knowledge of programming languages is only a small part of becoming a successful software engineer. In addition to programming, engineers also need to be proficient in design, engineering, architecture, communication, and collaboration. As long as everyone can do these things well, no matter which programming language you choose, you will become an outstanding software engineering guru.