Type Assertion
Part of the Object Oriented Programming section of Coddy's GO journey — lesson 29 of 107.
A type assertion extracts the concrete type from an interface value. When you have a value stored in an interface (like any), type assertion lets you access the underlying type and its specific methods or fields.
The syntax uses parentheses after the interface value:
var value any = "hello"
str := value.(string) // Extract the string
fmt.Println(str) // helloIf the assertion is wrong, your program panics. Asserting value.(int) when it holds a string causes a runtime error. To handle this safely, use the two-value form:
var value any = 42
str, ok := value.(string)
if ok {
fmt.Println("It's a string:", str)
} else {
fmt.Println("Not a string") // This prints
}The second return value ok is a boolean indicating whether the assertion succeeded. If it fails, ok is false and str receives the zero value of the asserted type.
Type assertions also work with non-empty interfaces. You can assert that an interface value implements another interface or is a specific concrete type:
type Speaker interface {
Speak() string
}
var s Speaker = Dog{Name: "Buddy"}
dog, ok := s.(Dog)
if ok {
fmt.Println(dog.Name) // Access Dog-specific field
}Always prefer the two-value form in production code to avoid unexpected panics when the underlying type doesn't match your expectation.
Challenge
EasyLet's build a data inspector that can safely extract and display information from values stored in the empty interface. You'll use type assertions with the two-value form to handle different types without causing panics.
You'll organize your code across two files:
inspector.go: Create a function calledInspectthat takes a value of typeanyand returns a descriptive string. Your function should use the two-value form of type assertion to safely check if the value is astring,int, orfloat64, and return an appropriate message for each type. If the value doesn't match any of these types, return a message indicating an unknown type.main.go: Read values from input, store them inanyvariables (converting to the appropriate types), then use yourInspectfunction to analyze each value and print the results.
The following inputs will be provided:
- Line 1: A string value
- Line 2: An integer value
- Line 3: A float value
Your Inspect function should return strings in these formats based on successful type assertions:
- For strings:
String value: [value] - For integers:
Integer value: [value] - For floats:
Float value: [value] - For unknown types:
Unknown type
For example, given hello, 42, and 3.14, your output should be:
String value: hello
Integer value: 42
Float value: 3.14Remember to use the safe two-value form value, ok := x.(Type) for each assertion. Check the ok boolean before using the extracted value, and try each type in sequence until you find a match or determine the type is unknown.
Cheat sheet
A type assertion extracts the concrete type from an interface value, allowing you to access the underlying type and its specific methods or fields.
Basic syntax:
var value any = "hello"
str := value.(string) // Extract the string
fmt.Println(str) // helloIf the assertion is wrong, your program panics. To handle this safely, use the two-value form:
var value any = 42
str, ok := value.(string)
if ok {
fmt.Println("It's a string:", str)
} else {
fmt.Println("Not a string") // This prints
}The second return value ok is a boolean indicating whether the assertion succeeded. If it fails, ok is false and the first value receives the zero value of the asserted type.
Type assertions work with non-empty interfaces too:
type Speaker interface {
Speak() string
}
var s Speaker = Dog{Name: "Buddy"}
dog, ok := s.(Dog)
if ok {
fmt.Println(dog.Name) // Access Dog-specific field
}Always prefer the two-value form in production code to avoid unexpected panics.
Try it yourself
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Read the string value
strVal, _ := reader.ReadString('\n')
strVal = strings.TrimSpace(strVal)
// Read the integer value
intLine, _ := reader.ReadString('\n')
intLine = strings.TrimSpace(intLine)
intVal, _ := strconv.Atoi(intLine)
// Read the float value
floatLine, _ := reader.ReadString('\n')
floatLine = strings.TrimSpace(floatLine)
floatVal, _ := strconv.ParseFloat(floatLine, 64)
// Store values in any variables
var val1 any = strVal
var val2 any = intVal
var val3 any = floatVal
// TODO: Use the Inspect function to analyze each value and print the results
_ = val1
_ = val2
_ = val3
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of Go OOP
External FilesGo Workspace & ModulesPackages & ImportsExported vs Unexported NamesIntroduction to OOP in GoStructs as ClassesDefining Methods on StructsPointer vs Value ReceiversStruct InitializationConstructor FunctionsRecap - Simple Calculator4Interfaces
Introduction to InterfacesImplicit ImplementationInterface as ContractEmpty Interface (any)Type AssertionType SwitchInterface CompositionStringer & Error InterfacesRecap - Shape Calculator7Encapsulation
Exported vs Unexported FieldsPackage-Level EncapsulationGetter & Setter MethodsInformation Hiding in GoRecap - Student Records10Generics (Go 1.18+)
Introduction to GenericsType ParametersType ConstraintsGeneric StructsGeneric Methods WorkaroundRecap - Generic Collection2Types & Structs Deep Dive
Basic & Composite TypesCustom Type DefinitionsStruct TagsAnonymous StructsNested StructsZero Values & DefaultsRecap - Contact Book5Composition Over Inheritance
Why Go Has No InheritanceStruct Embedding BasicsMethod PromotionEmbedding Multiple StructsEmbedding vs AggregationShadowing Embedded MethodsRecap - Employee Hierarchy8Error Handling & OOP
The error InterfaceCustom Error TypesError Wrapping (fmt.Errorf)Sentinel Errorserrors.Is() and errors.As()Panic, Defer, and RecoverRecap - File Parser3Pointers & Memory
Pointer Basics in GoPointers to StructsPass by Value vs ReferenceThe new() FunctionGarbage Collection in GoRecap - Linked List Builder6Polymorphism in Go
Polymorphism via InterfacesDuck Typing in GoInterface Satisfaction RulesPolymorphic CollectionsDependency InjectionRecap - Payment Processor9Concurrency & OOP
Goroutines BasicsChannels & CommunicationBuffered vs Unbuffered ChanSelect Statementsync.Mutex & sync.RWMutexsync.WaitGroupThread-Safe Struct DesignRecap - Worker Pool