Video Coming Soon...
22: Struct and Methods: Type Assertions and Switches
WARNING This exercise is in DRAFT status, so there may be errors. If you find any, please email me at help@learncodethehardway.com so I can fix them.
Go allows you to check the type of a variable and make decisions based on it. The syntax is a little odd, but easy enough to remember.
Asserting a Type
The first--and probably most useful--style is with two return results:
fruit, ok := thing.(Fruit)
This will confirm that thing
is of type Fruit
and cast it (convert it) to that type if it matches. The ok
part of the double return is true
if thing
is a Fruit
, and false
if thing
is not. This lets you check for thing
's type and safely handle it.
The other form is without the ok
second return and will cause a panic if the type does not match (like a more traditional assertion):
fruit := thing.(Fruit)
If you use this form and thing
is not Fruit
then your program will exit with a panic and tell you an error like this:
panic: interface conversion: interface {} is main.Animal, not main.Fruit
It's up to you what form to use, but I'd say if you require a certain type then...probably just use that type, or use the next thing the type switch
.
Type Assertion Example
Here's an example of using a type assertion to print out the name of Fruit
but not animals. Not too useful but we'll improve it in the next section.
View Source file ex22a/main.go Only
package main
import "fmt"
type Animal struct {
Name string
Age int
Species string
Weight float64
}
type Fruit struct {
Name string
Taste string
Smell string
}
func PrintName(thing any) {
fruit := thing.(Fruit)
if ok {
fmt.Println("Name", fruit)
} else {
fmt.Println("I can't print that")
}
}
func main() {
// this will work
durian := Fruit{"Durian", "Heaven", "Dead bodies and onions."}
PrintName(durian)
// this will fail
joey := Animal{"Joey", 3, "Kangaroo", 100.0}
PrintName(joey)
}
The type switch
A type switch
isn't any official Go syntax, but more the combination of type assertions with the switch
. You simply take the type assertion from above, but instead of a specific type in the ()
(parenthesis) you use the keyword type
like so:
switch v := thing.(type) {
case Animal:
// do animal things
case Fruit:
// do like fruit stuff
default:
// I don't know, error? Fish things?
}
This is how you might do different actions based on the type, which seems to come up most often with anything that handles events, but isn't limited to that use. You'll see this use of type switch
when we start making the Tiny Rogue Game at the end of this module.
type switch
Example
Next we have an example of a type switch
for you to study:
View Source file ex22/main.go Only
package main
import (
"fmt"
)
type Animal struct {
Name string
Age int
Species string
Weight float64
}
type Fruit struct {
Name string
Taste string
Smell string
}
func BadPrinter(thing any) {
switch what := thing.(type) {
case Animal:
fmt.Println("-- Animal named", what.Name)
fmt.Println(what.Name, "is", what.Age, "years old.")
fmt.Println(what.Name, "is a", what.Species)
fmt.Println(what.Name, "weighs", what.Weight)
case Fruit:
fmt.Println("-- Fruit named", what.Name)
fmt.Println(what.Name, "tasts like", what.Taste)
fmt.Println(what.Name, "smells like", what.Smell)
default:
fmt.Println("I don't know how to print a", what)
}
}
func main() {
joey := Animal{"Joey", 3, "Kangaroo", 100.0}
BadPrinter(joey)
durian := Fruit{"Durian", "Heaven", "Dead bodies and onions."}
BadPrinter(durian)
}
The Breakdown
The most important part of this code is the BadPrinter
function:
func BadPrinter(thing any) {
-- It's a function, but the important thing is theany
type, which allowsBadPrinter
to accept...any...type.switch what := thing.(type) {
-- SinceBadPrinter
doesn't know whatany
really is I use atype switch
to select what to do based on its type.case Animal:
-- For anAnimal
type I do this.case Fruit:
-- For aFruit
type I do this.default:
-- For anything else do this.
As you can see, it's a switch
like normal but you can use the type of a variable to make decisions instead of the value of the variable.
The Practice
- Break It -- Breaking these isn't too hard. In the first example you only need to remove the
ok
check and it'll explode. In thetype switch
example there's not much you can do since you are in total control of the results. - Change It -- See if you can use a
type switch
for the first example and if you like that better. - Recreate It -- I think for recreating this you might get more value out of thinking of your own example, describing it, then write code to implement it.
Study Drills
- Create 2 more types and add them to the
type switch
. - Why would I call this
BadPrinter
? Can you see any possible problems with doing this?
Register for Learn Go the Hard Way
Register today for the course and get the all currently available videos and lessons, plus all future modules for no extra charge.