Day 017 — Type Assertions & Type Switches¶
Month 1 · Week 3 · ⬅ Day 016 · Day 018 ➡ · Journal index
🎯 Learning Objective¶
Recover concrete types from interface values safely using type assertions (with the comma-ok form) and type switches, and know when not to.
📚 Topics¶
x.(T)single-value (panics) vsv, ok := x.(T)(comma-ok)- Asserting to a concrete type vs to another interface
switch v := x.(type)type switches ·defaultcase- Why over-using assertions is a design smell
📖 Reading / Sources¶
- Learning Go (Bodner) ch.7 — Type Assertions and Type Switches
- Tour of Go — Type assertions
- Tour of Go — Type switches
- Go spec — Type assertions
📝 Notes¶
- A type assertion
x.(T)extracts the concrete type/interface stored in interface valuex. The single-result forms := x.(string)panics if the dynamic type isn'tstring→ [[panic-recover]]. - Always prefer the comma-ok form:
s, ok := x.(string). Whenokis false,sis the zero value ofTand there's no panic. This mirrors map and channel-receive comma-ok → [[comma-ok-idiom]]. - You can assert to an interface type, asking "does this value also satisfy this other interface?":
if w, ok := r.(io.Writer); ok { ... }. Common for optional capabilities (e.g.interface{ Unwrap() error }). - A type switch handles many possible dynamic types cleanly:
switch v := x.(type) { case int: ...; case string: ...; default: ... }. Inside eachcase,valready has that case's type. With multiple types in one case (case int, int64:),vkeeps the interface type. - Type assertions are the mechanism behind
errors.Asandfmt'sStringer/Formatterchecks — but in your own code, leaning on them is often a smell. Prefer adding a method to the interface over switching on concrete types → [[interfaces]]. - A type switch's
defaultcatches anything unmatched; put it last. Anilinterface matchescase nil:.
💻 Code Examples¶
func describe(x any) string {
switch v := x.(type) {
case nil:
return "nil"
case int:
return fmt.Sprintf("int: %d", v)
case string:
return fmt.Sprintf("string of len %d", len(v))
case fmt.Stringer: // assert to ANOTHER interface
return "stringer: " + v.String()
default:
return fmt.Sprintf("unknown %T", v)
}
}
Full code:
examples/month-01/interfaces/main.go· Run:go run ./examples/month-01/interfaces
🏋️ Exercises / Practice¶
| Exercise | Status | Link |
|---|---|---|
Describe(any) string covering int/string/Stringer/nil/default |
✅ | exercises/month-01/week-3/shapes |
| Comma-ok assertion to skip non-matching values | ✅ | exercises/month-01/week-3/shapes |
🐛 Mistakes Made¶
- Used
n := x.(int)on a value that was astring→ runtime panicinterface conversion. Switched to comma-ok. - Put
defaultbefore other cases and expected fallthrough; type-switch cases don't fall through and order of non-default cases doesn't matter, butdefaultis the catch-all.
❓ Open Questions¶
- When is a type switch legitimately the right tool vs a method on the interface? (Legit for
errors.As-style unwrapping, formatting, and serializing heterogenousanydata.)
🧠 Active Recall (answer without looking)¶
-
Q: What's the difference between
s := x.(string)ands, ok := x.(string)?
A
The single-value form panics if the dynamic type isn't `string`; the comma-ok form sets `ok=false` and `s` to the zero value instead of panicking. -
Q: In
switch v := x.(type), what is the type ofvinsidecase int, string:?
A
It keeps the original interface type (e.g. `any`), because the case matches more than one type. With a single-type case, `v` has that concrete type.
🪶 Feynman Reflection¶
An interface value hides its real type behind a contract. A type assertion is you peeking under the hood asking "is this really a string?" The safe way to peek is comma-ok, which answers yes/no instead of crashing. A type switch is just a tidy stack of those peeks for many possible types at once.
🕳️ Knowledge Gaps¶
- Asserting to interfaces for "optional capabilities" — want more practice once I hit
iointerfaces.
✅ Summary¶
I can pull concrete types back out of interfaces safely with comma-ok assertions and type switches, and I know overusing them usually means I should have put a method on the interface instead.
⏭️ Next Steps / Prep for Tomorrow¶
- Day 018: errors as ordinary values, and wrapping them with
%w.
| Time spent | Difficulty | Confidence |
|---|---|---|
| 90 min | 🟦🟦⬜⬜⬜ | 🟦🟦🟦⬜⬜ |
Suggested commit: feat(examples): type assertions and type switches (day 017)