TL;DR
A developer who has spent several months building small projects in Go shares a personal, non-expert appraisal. They praise Go's built-in concurrency and simple type model but criticize the language's lack of enums, limited compile-time constants, and ergonomics of error handling.
What happened
A programmer who describes themselves as not an expert in Go spent several months using the language and wrote a candid review of its strengths and weaknesses. They highlight concurrency as a major win: goroutines, channels and select statements are first-class and generally easy to work with. The author appreciates Go’s intentionally simple type system, including struct embedding and implicit interface satisfaction, and prefers Go’s terse syntax and package-level visibility conventions. On the downside, they argue Go lacks a native enum type and that the common pattern of typed constants does not provide exhaustiveness guarantees. They also fault Go’s limited compile-time constants and the absence of broad immutability primitives. Finally, they critique Go’s error model: errors are represented by an interface exposing only an Error() string, and the language has no tuple type, which the author says makes error values less composable and forces brittle string-based checks in some real-world cases.
Why it matters
- Built-in concurrency primitives mean Go can simplify development of concurrent programs without external libraries.
- The lack of closed enums and exhaustiveness checking can make APIs less safe and put more burden on callers and linters.
- Limited compile-time constants and no general immutability features can expose exported package state to unintended mutation.
- The error-as-interface pattern and absence of tuple types may reduce the ability to programmatically inspect and handle specific error cases, affecting robustness.
Key facts
- Concurrency: goroutines, channels, and select are core language features and praised by the author.
- Struct embedding provides a way to reuse methods and fields; embedded methods can be called directly or via the embedded field.
- Interfaces in Go are satisfied implicitly; a type doesn’t need an explicit declaration to implement an interface.
- Go has no native enum type; common practice is to use typed constants with iota, which are not enforced as a closed set.
- Constants (const) in Go must be compile-time values; non-compile-time init data often uses vars.
- A common workaround for read-only exported state is to keep package-level vars private and expose accessors that return them.
- Errors are represented by the error interface, which only requires Error() string, hiding underlying structured error data.
- Go lacks a tuple type; what looks like (T, error) is handled by multiple return values and cannot be passed around as a single value.
What to watch next
- The author says they are considering returning to Rust after using Go for several months — watch whether they actually switch (confirmed in the source).
- Whether the Go language will add native enums, richer constant/immutability features, or more structured error types in future releases is not confirmed in the source.
Quick glossary
- Goroutine: A lightweight thread of execution managed by the Go runtime; goroutines are inexpensive to create and run concurrently.
- Channel: A language-level construct for communication and synchronization between goroutines; channels can pass typed values.
- Interface: A set of method signatures; in Go, a type satisfies an interface implicitly by implementing those methods.
- Struct embedding: A form of composition where a struct includes another struct directly, promoting the embedded type’s methods and fields.
- Enum (general): A closed set of named constant values grouped under a single type; useful for exhaustive pattern matching and safer APIs.
Reader FAQ
Is the reviewer an expert in Go?
No — the author states they have written a few small projects and explicitly says this is not expert opinion.
Does Go have enums?
No native enum type; the common pattern is typed constants (often with iota), which are not a closed set.
Are Go errors rich, type-safe values?
Not according to the author: errors are exposed via the error interface (Error() string), which can hide structured details and encourage string-based checks.
Can I make truly immutable compile-time values in Go?
Go’s const requires compile-time determinable values; many initializations require vars and are therefore mutable, per the author.
> 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
- Book Review: Go For Beginners – Boldly Go
- 33 Powerful Books That Might Change Your Life
- Comparing Guidebook Series
Related posts
- Is This the World’s First Solid-State Battery? CES Hype and Skepticism
- AI Coding Assistants Are Getting Worse, According to Recent Coverage
- Economists Say Supreme Court Decisions Have Shifted in Favor of the Wealthy