In the first part of this series, we explored some of Go’s unique choices—like the absence of enums, the ability to declare variables inside if statements, and how Go swaps traditional classes for structs and methods. These features set the tone for Go’s philosophy: simple, explicit, and practical.
Now that you’ve got a feel for the basics, it’s time to dig a little deeper. In this second post, we’ll look at some more of Go’s design decisions that might surprise you—like how interfaces work without declarations, or how functions can return multiple values with ease.
These features might not jump out at first, but they’re a big part of what makes Go so clean and developer-friendly in the long run. Let’s take a closer look at what makes this language tick.
Ready to level up your Go game? Let’s jump in. 🧭
1. Interfaces Are Implicit
In Go, a type implements an interface simply by having the necessary methods. No need to explicitly declare that a struct implements an interface.
type Greeter interface {
Greet() string
}
type User struct {
Name string
}
func (u User) Greet() string {
return "Hello, " + u.Name
}
func greetSomeone(g Greeter) {
fmt.Println(g.Greet())
}
User automatically satisfies the Greeter interface by implementing the Greet() method. It's seamless and flexible—perfect for dependency injection and testing.
2. Named Return Values
Functions in Go can have named return values, which act like pre-declared variables. This feature can make code more self-documenting and readable.
func getUserInfo() (name string, age int) {
name = "Alice"
age = 30
return
}
name, age := getUserInfo()
The return statement alone is enough to return the named values. It’s concise but can be controversial—some developers love it, others find it confusing.
3. Multiple Return Values
Functions in Go can return more than one value. This makes things like error handling super ergonomic:
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("division by zero")
}
return a / b, nil
}
res, err := divide(4, 2)
// res=2, err=<nil>
res, err := divide(4, 0)
// res=0, err=’division by zero’
This is a huge win for clarity, especially compared to languages that rely on out-of-band mechanisms like throwing exceptions.
4. A Built-in Formatting Tool: gofmt
One of Go’s best features isn’t even in the language—it’s the tooling. gofmt
automatically formats your code according to the community style. No
bikeshedding over curly brace placement!
Go’s charm lies in the balance it strikes between simplicity and power. Features like implicit interfaces and multiple return values aren’t just clever—they reduce boilerplate and force us to write more deliberate, expressive code.
And with tools like gofmt
baked right into the workflow, Go also takes a stance on team productivity and code clarity. You spend less time arguing over formatting and more time solving real problems.
If you’re still new to Go, don’t worry if some of these ideas take time to sink in. The more Go code you write, the more you’ll appreciate these little details that quietly make development smoother and more enjoyable.
Stay curious—and stay tuned for more Go insights in upcoming posts. 🧠💡