Go: A Discussion of Its Good and Bad Parts
This article summarizes a discussion about the Go programming language, highlighting both its strengths and weaknesses. The discussion covers topics like simplicity, error handling, generics, and the use of channels.
Go's Strengths
-
Developed by Prolific Developers: Go was developed by well-known and respected software developers.
-
Popularity and Publicity: It consistently ranks high in developer surveys and enjoys good publicity thanks to its use in large companies.
-
Performance Improvements: Companies like TypeScript are porting their compilers to Go to improve performance and simplify build pipelines. This shows Go's potential for efficient tooling.
-
Explicit Error Handling: Although controversial, some appreciate Go's explicit error handling, as it forces developers to acknowledge and handle potential issues directly.
-
Composition over Inheritance: Go favors composition over inheritance, which can lead to simpler and more predictable code.
-
Simplicity: Go aims for clarity and readability, making code easier to understand and maintain, even with larger teams.
Go's Weaknesses and Controversial Design Choices
-
Superficial Simplicity: Go's simplicity is sometimes seen as skin deep, sacrificing expressiveness for the sake of minimalism.
-
Forced Syntax Reuse: The lack of a
while
keyword, usingfor
loops instead, is seen as an unnecessary constraint that impacts readability. -
Public/Private Visibility: Using capitalization to determine public or private visibility can be easily overlooked and lead to accidental API breakage during refactoring.
-
Enum Implementation: The implementation of enums using
const
andiota
feels like a workaround rather than a proper language feature, lacking type safety and scoping. -
Multiple Return Values: While initially elegant, Go's multiple return values aren't first-class values, limiting their use in collections, channels, and generics, which increases verbosity.
-
Error Handling Verbosity: Managing errors in Go can be repetitive, with the same error-checking code repeated frequently.
-
Channels: Channels, while powerful, can be easily overused, requiring careful consideration and often coupling with context to avoid unexpected behavior.
-
Generics: While generics were introduced, their implementation is seen as limited and not fully satisfying. They cannot be used on method receivers in the desired ways.
-
Embedding: Embedding, intended as a form of composition, is not always well-implemented and can lead to questionable design choices.
-
Lack of Operator Overloading: Go does not support operator overloading, which may be a limitation for some developers, though others see it as beneficial for clarity.
Key Takeaways
-
Go prioritizes simplicity and readability, which can be a trade-off with expressiveness and flexibility.
-
Understanding the limitations of Go's design choices is crucial before committing to large projects.
-
Opinions on Go are often strong and polarized, with some developers loving its simplicity and others finding it too restrictive.
-
Context and Channels should be used together to prevent the application crashing because channel isn't set properly