Go Is a Well-Designed Language
Overall views on Go’s design
- Many agree Go hits its original goals: simple, productive for backends, fast compilation, good tooling, easy deployment (single static binary).
- Others argue “well‑designed” is too strong: they see many small, permanent missteps rather than deliberate tradeoffs.
- Several note that design should be judged against real-world use today, not just Google’s original constraints.
Error handling and type system
- Go’s
(T, error)pattern is criticized as semantically wrong for most functions: it’s a product type (4 logical cases) where a sum type (success or error) would fit better. - Lack of sum types, non‑nullable types, and first-class enums is seen as a core design gap; Go’s integer-based “enums” are error‑prone and need codegen or linters to be safe.
- Defenders argue explicit error values improve robustness and readability, though many wish for a
Result-like type and a?operator.
Simplicity, readability, and “anti‑cleverness”
- Supporters emphasize low cognitive load: fewer features, little metaprogramming, “you can hold the language in your head,” and codebases are easy to read years later.
- Critics counter that missing abstraction tools means more boilerplate and more code to read to grasp a high‑level intent (e.g., manually decoding every loop instead of map/filter/reduce).
Language quirks and inconsistencies
- Mentioned as bad or confusing design, not intentional tradeoffs:
nilslice vsnilmap behavior (append vs panic).time.Timezero value and custom epoch leading to subtle bugs when converted to Unix time.deferbeing function‑, not block‑scoped.- Strict unused‑import errors while silently allowing ignored errors.
Concurrency
- Goroutines and channels praised as a major practical win: easy to start, generally “do it once and forget.”
- Others say concurrency still adds heavy cognitive load (races, deadlocks, error fan‑out) and is often hidden behind libraries anyway.
Packages, folders, and circular dependencies
- Strong thread arguing that equating folders with packages plus a hard “no circular imports” rule fights natural ways humans categorize code.
- Others respond that it forces clearer boundaries or shared “types/util” packages and that large, flat or few‑package layouts work fine.
Ecosystem and comparisons
- Go is contrasted with Rust, Swift, Kotlin, Java, C#, Python:
- Seen as easier and more uniform than Java/Spring or .NET ecosystems.
- But less expressive and missing modern features compared to Rust/Kotlin/Swift.
- Some view Go as a “transition language” people outgrow; others see its conservatism and restraint on features as its main strength.