TL;DR
A developer who spent months writing Go praises its built-in concurrency primitives and straightforward type model but raises persistent complaints about the lack of enums, limited compile-time constants, and Go's error handling. The review contrasts Go's design choices with Rust's features around enums and richer error values.
What happened
A programmer with several small Go projects shared an experiential review after months of use. They praised Goroutines, channels and select as first-class concurrency tools that mostly avoid common concurrency pitfalls and are ergonomic to use. They also appreciated Go’s deliberately simple type system, including struct embedding and implicit interface satisfaction, plus concise visibility rules tied to identifier case. On the negative side, the reviewer criticized Go’s lack of a native enum or closed sum type, pointing out that the common iota-and-const pattern does not enforce a closed set and provides no compile-time exhaustiveness checks. They also flagged limitations around immutability: Go’s const requires compile-time constants so composite or runtime-known values must be exposed as vars or via accessor functions. Finally, the author argued Go’s error handling is hampered by errors being an interface that only exposes a string, and by the fact that (T, error)-style returns are not a first-class tuple type, which complicates chaining and structured error handling.
Why it matters
- Built-in concurrency primitives can simplify writing concurrent programs and reduce common errors.
- Absence of native enums and exhaustiveness checks can lead to runtime surprises unless guarded by discipline or tooling.
- Limitations on compile-time constants make expressing immutable exported data awkward and potentially error-prone.
- Error values that expose only text make programmatic discrimination of error cases harder and can force fragile string parsing.
Key facts
- Go treats concurrency as a core language concern: Goroutines, channels, and select are first-class.
- Struct embedding provides a lightweight composition mechanism and allows method reuse without classical inheritance.
- Interfaces in Go are satisfied implicitly; a type doesn't need explicit declaration to implement an interface.
- The empty interface (interface{} or any) enables dynamic typing patterns like runtime type switches.
- Go lacks a native enum or closed sum type; the common pattern uses typed constants and iota but does not enforce a closed set.
- Switch statements in Go do not provide compiler-enforced exhaustiveness for enumerations created with constants.
- const in Go is limited to compile-time constant values; composite or runtime-derived values must use var or be exposed via functions.
- Go’s idiomatic error type is an interface with a single Error() string method, which can hide structured error details.
- (T, error)-style multiple returns are convenient but tuples are not a first-class type in Go, limiting some higher-order patterns.
- The reviewer encountered code that relied on checking an error's string contents (from os.Stat) to determine a condition.
What to watch next
- Potential language proposals or community tooling addressing enums or closed sum types — not confirmed in the source
- Any changes or patterns to provide safer immutable exported data without relying on package-level vars — not confirmed in the source
- Developments in Go error handling strategies or standard library helpers for richer error introspection — not confirmed in the source
Quick glossary
- Goroutine: A lightweight thread managed by the Go runtime used to run functions concurrently.
- Channel: A typed conduit in Go for sending and receiving values between Goroutines, used for synchronization and communication.
- Interface: A set of method signatures; a type implements an interface implicitly by providing the required methods.
- Enum (closed sum type): A named type with a fixed set of possible values; languages that support it often provide exhaustiveness checks.
- Immutability: The property of a value that cannot be changed after it is created; support and enforcement vary by language.
Reader FAQ
Does the reviewer like Go's concurrency support?
Yes. They found Goroutines, channels and select to be well-integrated and generally pleasant to use.
Are enums available in Go?
No. The reviewer points out that Go lacks a native enum or closed sum type; developers typically use typed constants with iota.
Can you create immutable complex values as constants in Go?
No. Go's const requires compile-time constants, so composite or runtime-known values must be provided via vars or accessor functions.
Do Go errors carry structured information by default?
The reviewer argues they do not: the standard idiom uses an error interface that exposes only a string, making structured inspection harder.
Will the reviewer return to Go long-term?
not confirmed in the source
> An Honest Review of Go Published 2025-08-19 18:53:00 -05 I have written a few small projects in Go, so don’t assume what I am writing is expert opinion on…
Sources
- An Honest Review of Go (2025)
- 5 Golang Concurrency Mistakes That Are Silently Killing …
- Practical concurrency patterns in Go
- In-Depth Go Concurrency: A Practical Guide to Goroutine …
Related posts
- How Human Activity and Climate Signals Shaped 2025 Satellite Views
- A Practical, First-Hand Review of Go: What I Like and What I Don’t
- Is This the World’s First Solid-State Battery? CES Hype and Skepticism