Go through the eyes of a Rust programmer: first impressions

In anticipation of the start of the course “Golang Developer” prepared a translation of interesting material. What was your first impression of Go?


Over the past few weeks I have been able to use Go in work. I first used Go on a more or less large and serious project. Before that, I read a lot about Go and practiced examples and small programs while exploring the possibilities Rustbut real programming is a completely different matter.

I thought you might be interested to hear about my impressions. I will try not to get stuck in comparisons with Rust, but since this is my main language, they cannot be avoided. I must warn you in advance about a strong bias towards Rust, but I will do my best to be objective.

General impressions

Go programming is nice. The libraries had everything I needed without too many flaws. Learning was also a pleasant experience – it is a well thought out and practical language. As an example, if you learn the syntax, you will see that many idioms from other languages ​​are migrated to Go. Once you master the Go part, you can easily predict its capabilities. Having some experience in other languages, I could read and understand the Go code without any special Google help.

I noted a lot less frustration and a lot more productivity than using C / C ++, Java, Python, etc. However, Go is still felt as part of this generation of languages. He has learned from them, and I think this is probably the best language of this generation; but he is definitely part of this generation. It represents an incremental improvement rather than something fundamentally new (it should be noted that this is not a value judgment – increment is often beneficial in the world of software development). A good example of this is nil: languages ​​like Rust and Swift get rid of the null paradigm, thereby eliminating a whole class of errors. Go makes it less dangerous: no null values; delimitation of nil and 0. But the basic idea is still present, as well as the widespread runtime error of dereferencing a null pointer.

Ease of development

Go is incredibly easy to learn. I know that this is a propagated advertising slogan, but I was very surprised how quickly I was able to reach the level of productivity. Thanks to the documentation, tools, and the language itself, in just two days, I began to write informative code suitable for commits.

Several factors in favor of learning:

  • Go small. Many languages ​​try to be small, while Go is actually one. (This is mostly good, and I am impressed with the discipline that was required for this).
  • The standard library is good (and again also small). Finding and using libraries in an ecosystem is very easy.
  • The language has very little that is not in other languages. Go inherits many bits from other established languages, polishes them and neatly connects them. He carefully avoids novelty.

Code routine

Go code gets repetitive very quickly. It lacks any mechanism such as macros or generics to reduce repetition, (interfaces are good for abstractions, but not so good for reducing code duplication). I often accumulate a large number of functions that are identical except for types.

Error handling also contributes to repetition. Many features have more templates. if err != nil { return err }than the original code.

Using generics or macros to reduce the routine of code is sometimes criticized for the tradeoff with its readability. But in the case of Go, I would not agree with them. Copying and pasting code is quick and easy, but reading Go code can be frustrating because you must ignore most of it or look for subtle differences.

What i liked

  • Compilation time. Definitely fast; definitely much faster than Rust. But actually it’s not as fast as I expected (it seems to me that it is at the C / C ++ level or even a little faster for medium and large projects, and I expected something almost instantaneous).
  • Goroutines and channels. The lightweight syntax for running Go routines and using pipes is really good. Such a small detail, which makes parallel programming much nicer than in other languages, really shows the power of the syntax.
  • Interfaces They are devoid of sophistication, but they are easy to understand and use, and they are useful in many places.
  • if ...; ... { } syntax. The ability to limit the scope of variables to the body of if statements is good. This is akin to if let in Swift and Rust, but more general-purpose (Go does not have a matching pattern like Swift and Rust, so it cannot use if let).
  • Test and dock comments are easy to use.
  • The Go tool is nice – all at once in one place without having to connect many tools through the command line
  • In stock garbage collector (GC)! No need to care about memory management really makes programming easier
  • Varargs.

What I didn’t like

The order does not matter.

  • nil slices – nil, nil slices and empty slices are all different things. I’m more than sure that you only need two of them, not all three.
  • No primary classes. The use of constants is unusual.
  • Ban on import cycles. This really limits the usefulness of packages designed to modularize a project, as it encourages packing a large number of files into one package (or many small packages, which can be just as bad if the files that need to be together are distributed in different packages).
  • switch may not be exhaustive
  • for ... range returns an index / value pair. Retrieving only the index is easy (just ignore the value), but retrieving only the values ​​requires explicit indication. For me it’s a scruff, because in most cases I need a value, not an index.
  • Syntax:
    • Inconsistency between definitions and uses.
    • Selectivity of the compiler (requiring or prohibiting, for example, hanging commas); this is mainly facilitated by a good set of tools, but there are several cases where this creates an annoying extra step.
    • When using return types with multiple values, brackets are required for the type, but not for return.
    • Declaring a structure requires two keywords (type and struct).
    • Capitalization to indicate public or private variables. It’s like a Hungarian notation, only worse.
  • Implicit Interfaces I know that this is also on the list of what I like, but sometimes it is really annoying, for example, if necessary, find all types that implement an interface, or interfaces implemented for a given type.
  • You cannot write functions with a receiver in another package, therefore, even if interfaces are typed implicitly, they cannot be implemented for higher types, which makes them much less useful.

I already mentioned the lack of generics and macros above.

Coherence

As a language developer and programmer, I was probably most surprised by the fact that Go often encounters a mismatch between what is built-in and what is available to users. The task of many languages ​​is to dispel as much magic as possible and make built-in functions available to users. Operator overloading is a simple but controversial example. Go has a lot of magic! And you very easily bump into a wall of inability to do what built-in things can do.

Some points that stand out particularly:

  • There is good syntax for returning multiple values ​​for channels, but they cannot be used together because there are no tuple types.
  • There is an operator for ... range for iterating over arrays and slices, but you cannot iterate over other collections because the concept of iterators is missing.
  • Features like len and appendare global, but you cannot make your own functions global. These global functions only work with built-in types. They can also be universal, even if Go has no generics!
  • No operator overload. This is especially annoying when used. ==, because this means that you cannot use custom types as keys for a map if they are not comparable. This property is derived from the type structure and cannot be overridden by the programmer.

Conclusion

Go is a simple, compact, and enjoyable language. It has a few sharp corners, but mostly it is well designed. He is incredibly quick to learn and avoids any features that are not known in other languages.

Compared to Rust, Go is a completely different language. Although both of them can be roughly described as system languages ​​or “replacements” for C, they have different goals and applications, language design styles and priorities. Garbage collection is really a big difference. Having GC in Go makes the language much simpler and smaller, and easier to understand. The absence of GC in Rust makes it very fast (especially if you need a clear delay, and not just high bandwidth) and provides features and programming patterns that are impossible in Go (at least without sacrificing performance).

Go is a compiled language with a well-implemented runtime. He is fast. Rust is also compiled, but has a much smaller runtime. He is very fast. Assuming there are no other restrictions, I think that choosing between using Go and Rust is a trade-off between a much shorter learning curve and simpler programs (which means faster development) and, on the Rust side, more speed and a more expressive system types (which makes your programs safer and speeds up debugging and troubleshooting).


On this the translation has come to an end, and we invite you to free hands-on online lesson, where you will learn how to create a fully tested http service from scratch in 60 minutes without 3rd-party dependencies.


Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *