Making “switch” Cool Again: Go Reinvents the Extremely Useless Syntax

Image for post
Image for post

The switch statement is seldom used in most applications, but appears in almost all programming languages. I believe this is because switchis only useful in a very specific case. Thankfully, Go took a step back and said “we don’t have to do it the way everyone is used to” and rethought what it means to handle lots of branches of the same decision point without resulting to a chain of ifstatements.

The “break” Killed the “switch”

Consider the simplest and most obvious use of a switch in C++. Most languages that implement switchwill use a similar syntax:

int dayOfTheWeek = 3;
char *dayName = null;
switch (dayOfTheWeek) {
case 1:
dayName = "Monday";
break;
case 2:
dayName = "Tuesday";
break;
case 3:
dayName = "Wednesday";
break;
case 4:
dayName = "Thursday";
break;
case 5:
dayName = "Friday";
break;
case 6:
dayName = "Saturday";
break;
case 7:
dayName = "Sunday";
break;
}

I realise this could be reduced to an array; just pretend these are more random values if you wish. This is already long and cumbersome, however it is slightly neater but longer than the alternative with chained if else statements:

int dayOfTheWeek = 3;
char *dayName = null;
if (dayOfTheWeek == 1) {
dayName = "Monday";
} else if (dayOfTheWeek == 2) {
dayName = "Tuesday";
} else if (dayOfTheWeek == 3) {
dayName = "Wednesday";
} else if (dayOfTheWeek == 4) {
dayName = "Thursday";
} else if (dayOfTheWeek == 5) {
dayName = "Friday";
} else if (dayOfTheWeek == 6) {
dayName = "Saturday";
} else if (dayOfTheWeek == 7) {
dayName = "Sunday";
}

To me this is very ugly, repeats a lot of code and is less explicit than the switch version, but since it’s shorter and more flexible it’s usually the preferred option. Now let’s see how Go handles it:

dayOfTheWeek := 3
var dayName string
switch dayOfTheWeek {
case 1:
dayName = "Monday"
case 2:
dayName = "Tuesday"
case 3:
dayName = "Wednesday"
case 4:
dayName = "Thursday"
case 5:
dayName = "Friday"
case 6:
dayName = "Saturday"
case 7:
dayName = "Sunday"
}

Yes! Now we get to the crux of it. The breakstatement is the wart that has killed the beautiful simplicity of the switch. It should have been original designed with the intention that in the vast majority of cases you will only want one case to match and not have to pollute your source with breakstatements.

Collapsing Cases

Since the normal implementation relies on the breakto not fall through; several cases can grouped. Go takes it one step further by comma separating all the matching values. This is less typing and even more explicit:

dayOfTheWeek := 3
var dayName string
switch dayOfTheWeek {
case 1, 2, 3, 4, 5:
dayName = "Weekday"
case 6, 7:
dayName = "Weekend"
}

Expressions

The other reason why switchis seldom used is because in many languages the value that it’s switching on must by a primitive, sometimes even restricted to an integer. Go removed this limitation as well by allowing complete expressions for cases:

switch {
case dayOfTheWeek <= 5:
dayName = "Weekday"
case dayOfTheWeek > 5:
dayName = "Weekend"
}

If you use expressions for cases you do not need to even specify a switch value. This works more like a chained ifstatement. Furthermore, Go’s ability to declare scoped variables makes this switch even more readable:

dayOfTheWeek := 3
var dayName string
switch friday := 5; true {
case dayOfTheWeek <= friday:
dayName = "Weekday"
case dayOfTheWeek > friday:
dayName = "Weekend"
}

Empty Cases

Empty cases mean it does nothing:

switch hasHadCoffee {
case false:
// Don't talk to me.
case true:
readyToTalk()
}

Falling Through

If traditional switches rely on break statements to not fall through, then fallthrough would be the opposite. A casenever falls through unless you have an explicit fallthrough:

count := 0switch {
default:
count++
fallthrough
case false:
count++
}

It’s important to recognise that countis 2 because fallthroughwill always run the next case, even if it wouldn’t normally be hit.

Type Switching

One great thing about Go is that type casting and assertions can be put into the same line:

var value interface{} = "hello"
if str, ok := value.(string); ok {
// str must be a string
} else {
// error handling
}

If there are more than one possible expected type you can do the same thing with a switch:

var value interface{} = "hello"
switch o := value.(type) {
case string:
// o is a string
case int:
// o is an int
default:
// Handle the unknown type
panic(o)
}

Conclusion

Go not only makes switch useful, it reinvigorates and promotes it to a powerful and flexible tool. I believe similar functionality could be implemented in other languages by using functions and arrays… Maybe a side project there.

Originally published at http://elliot.land on February 27, 2016.

I’m a data nerd and TDD enthusiast originally from Sydney. Currently working for Uber in New York. My thoughts here are my own. 🤓 elliotchance@gmail.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store