Source: InfoQ
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 the survey respondents stating that they are Rust users. 29.7% of the respondents indicated that they use Rust for most of their coding work, a significant increase of 51.8% compared to the previous year.
Undoubtedly, Rust is increasingly becoming the focus of developers due to its outstanding memory safety and concurrent performance. However, equally hard to ignore is Go, a relatively "veteran" contender that was once voted as the programming language of the year.
Go was born in 2009 and initially received great attention for its unique concurrency model and powerful performance advantages. It is worth noting that, like the creators of Rust, the creators of Go also "hate" C++, and Go is also a dominant language in cloud-native development.
In the Stack Overflow 2022 Developer Survey, in response to the question of "the love-hate relationship with programming languages," out of 70,000 responses, programmers clearly showed a greater preference for Rust, with 86% expressing their fondness for Rust, while 64% expressed their fondness for Go. Faced with the popularity of Rust, some developers have raised the soul-searching question: Is it still worth learning Go in 2023?
Moreover, the question of whether to choose Rust or Go has also become a hot topic on Hacker News in recent days:
A Rust supporter said, "I also struggled with this choice for a long time. In the end, Rust won. First, I feel that Rust is closer to something from the Pascal era, where you can control everything; second, if WebAssembly and related technologies explode, Rust will be a safer choice; then, 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 has received attention, so it is unlikely to be eliminated."
Another developer who holds the opposing view said, "I have been working with Go for almost ten years, but recently I also tried Rust. I think there is currently some mandatory and misleading preference for Rust, based on my experience in various startups, including the company I am currently in, for backend development, Go is by far the best choice! Note, in terms of performance, features, or other aspects… these two languages are very, very similar!"
It must be said that both Go and Rust are excellent programming languages. They are modern, powerful, widely used, and have excellent performance. However, it really doesn't make much sense to directly compare which is better between Go and Rust, as each programming language represents a series of deep trade-offs behind it. Different languages are optimized for different needs, so when choosing a language, we should also consider what kind of problems we want to solve with it. Therefore, we will start from the applicable scenarios of Go and Rust languages and discuss the "way" of their design.
Although Rust and Go differ greatly in syntax and style, they are both first-class tools for building software. Let's start the specific analysis below.
Go and Rust: Similarities
Rust and Go have many similarities, which is why they are often compared. 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
And:
Go is an open-source programming language that makes it easy to build simple, reliable, and efficient software.
—golang.org
Memory Safety
Go and Rust both belong to modern programming languages that emphasize memory safety. Over the past few decades of development of old languages such as C and C++, we have clearly realized that one of the core reasons for errors and bugs is unsafe/incorrect memory access.
As a result, Rust and Go each provide different solutions, but their goals are to be smarter and safer in memory management, helping developers write correct and highly performant programs.
Fast, Compact Executable Files
Both are compiled languages, meaning 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 do not need to distribute interpreters and a large number of libraries/dependencies with the program. As a direct manifestation of this core advantage, Rust and Go programs often run faster than interpreted languages.
General-Purpose Languages
Rust and Go are both powerful and scalable general-purpose programming languages that can be used to develop various modern software—from web applications to distributed microservices, as well as embedded microcontrollers and mobile applications, among others.
Both have excellent standard libraries and thriving third-party ecosystems, in addition to strong commercial support and a large user base. Both have been around for many years and will continue to maintain strong development momentum in the coming years. Therefore, learning Go or Rust at this time is a very reasonable investment of time and effort.
Pragmatic Programming Style
Both Rust and Go do not lean too much towards functional languages (such as Scala or Elixir) or fully object-oriented languages (such as Java and C#). Instead, while both have functional and object-oriented programming capabilities, they always emphasize a pragmatic approach—solving problems in the most appropriate way, rather than forcing everyone to use a specific method through "ideology."
However, if you do prefer a functional programming style, Rust offers more related tool options, which is also an advantage of Rust over Go.
We can certainly argue about what a truly "object-oriented" language is. 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
Large-Scale Development
Rust and Go provide many useful features for large-scale programming, so they can adapt to the practical needs of large development teams and large codebases.
For example, C programmers have been arguing for years about where to put parentheses and whether to use tabs or spaces for indentation; but Rust and Go have long since resolved these issues by using standard formatting tools (Go has gofmt, while Rust has rustfmt) to automatically rewrite your code.
This does not mean that this specific format is particularly clever, but Rust and Go programmers are more pragmatic and prefer a unified standard of execution.
While gofmt's style may not be everyone's favorite, gofmt can help everyone.
—Rob Pike
Another major advantage of these two languages is reflected in their build pipelines. Both have excellent, built-in, and high-performance standard build and dependency management tools. This means that programmers do not have to fight complex third-party build systems, nor do they need to learn a new system every few years.
In the early stages of my career, I used Java and Ruby, so writing Go and Rust code has always made me a little apprehensive and made me feel like I couldn't handle it. But when I entered Google and saw the 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 studied it on small-scale projects, I can see its ease of use. I hope that those infinitely configurable build systems will become history soon. New languages now come with their own dedicated build tools and can be used out of the box. Isn't that good?
—Sam Rose
Choosing Rust or Go?
After discussing so many issues, and with both languages designed so well and powerful, does this comparison have a result? Or, since both are excellent options, why do people still express anger on social media and write lengthy comments and blog posts like "only idiots use Rust" or "Go can't even be considered a programming language"?
Some people are certainly just venting their emotions, but this obviously does not help solve practical problems. At least in the matter of which language to use in a project, or which language to rely on to venture into the programming world, raising one's voice clearly does not help make the right choice.
Let's return to the discussion of rational analysis and see how Rust and Go have their own strengths and weaknesses.
Go on Rust: Performance
As mentioned earlier, programs generated by Go and Rust run very fast because they are compiled into native machine code, without the need for an interpreter or virtual machine.
However, Rust's performance is even better, and it can even compete with the industry-standard performance benchmarks of C and C++. Unlike these traditional languages, Rust also provides memory safety and concurrency safety mechanisms, with almost no impact on execution speed. Rust also allows developers to build complex abstractions without sacrificing performance at runtime.
In comparison, although the performance of Go programs is also good, its design focus is mainly on development speed (including compilation), rather than execution speed. Go programmers tend to prioritize clear and readable code, so the running speed is slightly inferior.
The Go compiler also does not spend too much time generating the most efficient machine code; it is more concerned with how to quickly compile a large amount of code. 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 very efficient and has been optimized to minimize pause times as much as possible (pause times have also been getting shorter with each new release of Go). However, regardless, garbage collection always introduces some unpredictability to the behavior of the program, which can be very serious, or even completely unacceptable, for certain specific applications (such as embedded systems).
Because Rust aims to give programmers complete control over the underlying hardware, Rust programs can be deeply optimized to approach the maximum theoretical performance of the machine. As a result, Rust becomes the best option in specific use cases where execution speed surpasses everything else, such as game programming, operating system kernels, web browser components, and real-time control systems.
- Simplicity
If a programming language is too difficult to learn and keeps most people out, its performance is meaningless. In design, Go seems to deliberately differentiate itself from languages with increasing complexity like C++: it has very few syntax, very few keywords, and even fewer features.
This means that Go is easy to get started with and can be used to write various programs after a little understanding.
Go is indeed very easy to learn. I had often heard people mention this, but after using it, I was still surprised at how it could quickly improve work efficiency. 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 easy. A small and simple language is definitely easier to learn than a large and complex language. There are not many ways to achieve a certain effect, so high-quality Go code looks almost the same. This also brings another benefit: we can quickly understand what a service we are not familiar with is doing.
Although the core of Go is small, its standard library is very powerful. This means that in addition to learning Go syntax, we must also consider the learning curve of the standard library.
On the other hand, moving functionality from the language to the standard library means that we only need to focus on learning the libraries relevant to our current development needs. Go is also designed to fully support 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.
Using the Go language, junior developers often find it easier to improve work efficiency, but it is more difficult for intermediate developers to introduce complex abstractions and thus cause problems. Because of this feature, Rust's appeal in enterprise software development is often not as strong as Go's.
— Loris Cro
- Functionality
Rust supports more complexity than several other programming languages, so its implementation scope is also larger.
— Devathon
Rust is specifically designed to include various powerful and useful features that can help programmers accomplish more tasks with less code. For example, Rust's matching feature allows for the quick creation of flexible and expressive logic:
But because Rust is designed to consider more, it is a bit more difficult to learn, especially at the beginning. But that's okay, after all, C++ or Java also have a lot to learn, and they cannot even provide advanced features like memory safety that Rust does. So the criticism that Rust is too complex is really not reasonable: it emphasizes expressiveness and rich functionality, and we cannot expect it to be so simple and pure while enjoying these advantages.
So Rust certainly has its own learning curve. But once you get past that hurdle, the rest is smooth sailing.
If you are ready to learn more complex syntax and semantics (and a higher threshold for code readability), and in return achieve the highest level of performance, then Rust is even capable of competing with C++ and D. — Dave Cheney
Although Rust and Go have borrowed some features from each other (such as generics), it is fair to say that Rust's features are more superior, while Go's features are relatively lacking.
- Concurrency
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 provides a lightweight alternative: goroutines. Each goroutine is an independently executing Go function, and the Go scheduler maps it to one of the controlled operating system threads. This means that the scheduler can efficiently manage a large number of concurrent goroutines using a limited number of operating system threads.
As a result, 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 very high, and the user experience is quite pleasant and easy.
In general, designing concurrent programs is very difficult, and building reliable and correct concurrent programs in any language is not an easy task. But because this need was considered from the beginning, the concurrency mechanism in Go has been made as simple and well-integrated as possible.
Go allows us to more easily build an application that can be carefully deconstructed and deployed as a set of microservices, fully leveraging its concurrency advantages. Rust can also do this, but it is more difficult to implement. In a sense, Rust is more suitable for programmers who absolutely do not allow security vulnerabilities due to memory issues; but correspondingly, they have to put in more effort to perform certain tasks that are relatively simple for other languages (including Go). —Sonya Koptyev
In contrast, the concurrency mechanism in Rust has just landed and is not yet stable, so we continue to welcome everyone's attention to this active development direction. This also has its benefits, for example, the rayon library in Rust provides a very elegant and lightweight way 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 in other languages.
—Early impressions of Rust programmers on Go
Although implementing concurrent programs in Rust may be a bit difficult, it is completely feasible, and these programs also benefit from the memory safety guarantees carefully designed in Rust. For example, in the standard library's Mutex class in Rust, we may forget to acquire a mutex before accessing certain content in Go; but in Rust, this is completely unnecessary.
Go focuses on making concurrency one of its most core concepts. This is not to say that we cannot achieve similar concurrency effects in Rust as in Go, but the difficulty of implementation is a test for programmers. Go focuses on making concurrency one of its most core concepts. This is not to say that we cannot achieve similar concurrency effects in Rust as in Go, but the difficulty of implementation is a test for programmers.
—Dave Cheney
- Safety
As mentioned earlier, Go and Rust both prevent various common programming errors in their own ways, especially those related to memory management. However, Rust goes further and spares no effort to ensure that everyone does not make unexpected safety loopholes.
Rust's compiler is so strict that it checks every variable we use, every memory address we reference. It avoids potential data race situations and notifies you of undefined behavior. In Rust's world, concurrency and memory safety issues are almost impossible to occur.
—Why choose Rust?
In other words, the programming experience in Rust is different from almost all other languages, and can be quite challenging when first encountered. But for many developers, this effort is clearly worthwhile.
For me, the biggest advantage of Rust is that the compiler has become my good assistant, it does not miss any bugs detected (to be honest, sometimes I feel like it has magical powers).
—Grzegorz Nosek
Many languages, including Go, 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 it feels wonderful. — Sam Rose
"Struggling with the borrow checker" is a hurdle that newcomers to Rust must overcome, but in most cases, the checker is not really the enemy. The problems it finds are indeed real bugs in the code (or at least potential bugs). It may force us to fundamentally refactor our program to avoid such problems—if you truly prioritize correctness and reliability, then this strict requirement is clearly a good thing.
From another perspective, can a new language that does not change the way of programming be called a new language? And when using other languages, Rust also teaches us to think about safety, which is equally significant.
If people choose Rust, it is often because they want to use its protective design: safety regarding null pointers/data races, predictable runtime behavior, and complete control over hardware. If these things are meaningless to you, then there is really no need to use Rust. After all, these benefits come at a cost: it is very difficult to get started. You have to change 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 which other languages you have used before. Python or Ruby programmers may find Rust too restrictive, but others may find the clear and explicit constraints to be 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 "struggling with the borrow checker" becomes "can the compiler be used like this? Cool!"
— Grzegorz Nosek
- Scalability
Today's server programs consist of tens of millions of lines of code, written by hundreds or thousands of programmers, and are updated almost every day. In the design and development of Go, full consideration has been given to the efficiency improvement needs in such environments. 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 a small team, choosing a simple language or a rich language is purely a matter of personal preference. But as software scales, complexity increases, and teams expand, the differences between the two types of languages begin to truly emerge.
For large applications and distributed systems, the importance of code execution speed is often lower than development speed: languages like Go, which deliberately emphasize a streamlined design, can shorten the adaptation time for new developers and allow them to contribute to large codebases more quickly.
Using the Go language, junior developers often find it easier to improve work efficiency, but it is more difficult for intermediate developers to introduce complex abstractions and thus cause problems. Because of this feature, 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 sophistication and elegance. The limitations of Go actually make it more suitable for the needs of enterprises and large organizations compared to 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 are targeting completely different use cases.
The entire programming approach of Go is completely different from Rust, and these features are particularly suitable for some people, but they can also completely infuriate others. This is normal, because if Rust and Go are both solving the same basic problems in a fundamentally similar way, why do we need two independent languages?
So, can we start by taking the approaches taken by Rust and Go and interpreting their essence? Let's try that below.
- Garbage Collection
"Whether to have garbage collection or not" is always a question without a correct answer. In general, garbage collection and automatic memory management can help us develop reliable and efficient programs quickly and easily. So for some developers, these are essential features.
But some people believe that garbage collection and the performance overhead and global pauses it brings can make the behavior of the program unpredictable and introduce unacceptable delays. This argument also makes sense.
Go and Rust are two completely different languages. Although both can be simply described 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, more compact, and easier to understand. The absence 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), and also achieves a series of features and programming patterns that Go cannot possibly achieve (at least without sacrificing performance).
— PingCAP
- Close to Hardware
The history of computer programming can be seen as a development of increasingly complex abstractions. 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. But for some other programs, access to hardware and precise control of program execution are more important.
The goal of Rust is to allow programmers to "get close to the hardware" and regain more control, while Go abstracts away architectural details and allows programmers to get closer to the problem.
The two languages have different application scopes. Go is good at writing microservices and typical "DevOps" tasks, but it is not a systems programming language. Rust is more powerful in tasks that emphasize concurrency, safety, and/or performance, and its learning curve is indeed steeper than Go's.
— Matthias Endler
- Performance First
In fact, for most programs, the importance of performance is less than that of code readability. But if some projects do prioritize performance, then many of the design trade-offs in Rust will help push the code's execution speed to the limit.
In contrast, Go cares more about 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.
Rust's performance is better than Go's. In benchmark tests, Rust is indeed faster, sometimes even by an order of magnitude. But before choosing the Rust language, please understand one thing: Go is not far behind in most benchmark tests, and it still maintains a performance advantage over languages like Java, C#, JavaScript, and Python.
If you need top performance, then you can choose either of these two languages, and the 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
- Correctness
On the other hand, if we don't insist that the program never makes a mistake, the trade-offs will be different. Most code does not consider long-term use, but some programs do indeed run in production for many years. Faced with these realities, perhaps we need to invest a little extra time to develop and ensure that the program runs correctly, reliably, and does not cause a heavy maintenance burden in the future.
Go and Rust can both help us write correct programs, but in different ways: Go provides an excellent built-in testing framework, while Rust focuses on eliminating runtime bugs through the borrow checker.
My view is: for code that needs to be released tomorrow, use Go; if it must run stably for 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 conclusion, other people's opinions are not important: only you can decide which programming language is best for your team and project needs.
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, then the Go language is definitely the right answer. Go specifically focuses on concurrency design and keenly identifies unsafe memory access behaviors (which Rust can also do), but it does not force you to manage every detail one by one.
Go is fast and powerful, but its core highlight is helping developers get out of trouble, focusing on simplicity and uniformity. On the other hand, if you need to make the most of every bit of performance space, then Rust is the ideal choice.
— Andrew Lader
In conclusion, I hope this article helps everyone understand the highlights of Rust and Go. If possible, it's best to experience both of these languages to some extent, as they are very useful in any technical path, even for amateur programmers.
But if you only have time to seriously study one language, please make sure to understand the strengths and tendencies of both 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 you can do these things well, no matter which programming language you choose, you will become an excellent software engineering expert.
免责声明:本文章仅代表作者个人观点,不代表本平台的立场和观点。本文章仅供信息分享,不构成对任何人的任何投资建议。用户与作者之间的任何争议,与本平台无关。如网页中刊载的文章或图片涉及侵权,请提供相关的权利证明和身份证明发送邮件到support@aicoin.com,本平台相关工作人员将会进行核查。