Avoiding Type Assertions in Go

Prefer Polymorphism to Conditionals

Clay Shentrup
Nov 29, 2019 · 2 min read
Photo by JOSHUA COLEMAN on Unsplash

Since coming to Go from Ruby, I’ve been a lot happier and less stressed out. I used to spend a lot of time admonishing developers to prefer composition to inheritance and avoid optional arguments. Go avoids these arguments by simply (and deliberately) lacking both inheritance and optional args. In general, the recommended best practices contain sage wisdom that can avoid a lot of the mistakes especially common among junior developers.

But one area where I feel the language authors go astray is in their use of type assertions, which tie conditional behavior to types. See this example from the encoding/xml standard library.

// CopyToken returns a copy of a Token.
func CopyToken(t Token) Token {
switch v := t.(type) {
case CharData:
return v.Copy()
case Comment:
return v.Copy()
case Directive:
return v.Copy()
case ProcInst:
return v.Copy()
case StartElement:
return v.Copy()
}
return t
}

What’s so bad about conditionals like these? In short, they scatter behavior about a group of related types across the file system, making change more costly. This leads to a code smell called Shotgun Surgery. Every time a new relevant type is added (or removed), changes will have to be made to switch statements like this one, across the system. This problem has been eloquently discussed ad nauseam by the inimitable Sandi Metz, who you can see working her magic in this talk.

Sandi Metz teaching us about the benefits of polymorphic design.

Unsurprisingly, the Very Senior Developers on the Go team stumbled right into this mess in the standard library, scattering switch statements like the one above across multiple files.

The Solution

The easy alternative here is to simply move the Copy() method to the respective concrete types which implement the Token interface (e.g. CharData). Then the conditional, e.g. the switch statement, is only needed once, to return the correct type to implement methods like Copy(). This notion of using various types to satisfy an expected interface is known as duck typing, and Go thankfully makes it a first class citizen via the interface keyword. If you find yourself typing t.(type), there’s probably a better way.

Extreme Programming

About Extreme Programming

Clay Shentrup

Written by

Advocate of Score Voting and Approval Voting. Software engineer. Father. Husband. American.

Extreme Programming

About Extreme Programming

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade