If you’re a new developer getting started with Go (or coming from a language like Python, JavaScript, or Java), you might be surprised by how… different it feels. Go was designed with simplicity and clarity at its core—but that doesn’t mean it’s boring.
In fact, Go makes some bold choices that might feel strange at first—like skipping enums entirely or handling errors without exceptions. But these decisions aren’t random. They’re intentional, and they shape the way you write software in Go: explicit, clean, and often refreshingly minimal.
In this article, we’ll walk through a few of these Go-specific quirks that tend to catch beginners off guard, and show how they’re actually features that make the language uniquely powerful.
1. No Enums, But There Are Constants
In many languages, enumerations (enums) are a standard way to represent a set of related constants. Go doesn’t have enums in the traditional sense, but it does offer an elegant alternative using const and iota.
const (
Small = iota
Medium
Large
)
Here, iota auto-increments with each line, assigning Small = 0, Medium = 1, and Large = 2. It’s simple, readable, and does the job—though developers used to robust enum systems may find it a bit barebones.
2. Declare and Initialize Inside if
Go allows you to declare a variable directly inside an if statement, scoped only to that block. This keeps your code clean and prevents pollution of the outer scope.
if value, err := someFunction(); err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Value:", value)
}
No need to declare value or err beforehand—Go keeps it tight and contextual. Once you leave the if block, those variables are gone.
3. Short Variable Declarations with ‘:=
’
Go makes variable declarations simple with the := operator. It lets you declare and initialize a variable in one line, with the type inferred automatically:
count := 10
message := "Hi there"
This shorthand keeps code clean and is widely used inside functions. Just note that := is only for new variables and only works within function scope—use =
to reassign values later.
4. No Classes, But Methods on Structs
Go doesn't have traditional classes or inheritance. Instead, it uses structs and interfaces. But don’t worry—you can still attach methods to types.
type User struct {
Name string
}
func (u User) Greet() string {
return "Hello, " + u.Name
}
This makes Go feel closer to a procedural language with powerful object-oriented features hiding just beneath the surface.
5. No Exceptions, Only Errors
Go doesn’t have exceptions. Instead, it handles errors explicitly:
val, err := doSomething()
if err != nil {
return err
}
At first, this feels verbose, but it encourages you to always think about failure cases—which leads to more robust software.
Go may not have all the bells and whistles of some modern programming languages, but that’s by design. Its minimalism forces clarity, and its quirks—once understood—often lead to better, more maintainable code.
As you keep learning, you’ll discover that Go’s simplicity doesn’t limit you; it gives you a strong foundation to build from. Whether it's declaring variables inside if blocks or handling errors explicitly, these patterns become second nature with time.
Stick with it, and Go will reward you with fast compilation times, readable code, and a strong community that values clean engineering over clever tricks.