Embedded Interface and Type Assertions
This lesson explains how embedding the interfaces works like a charm and how a function is called depending upon the type of interface decided at runtime.
We'll cover the following
Interface embedding interface(s)
An interface can contain the name of one (or more) interface(s), which is equivalent to explicitly enumerating the methods of the embedded interface in the containing interface.
For example, the interface File
contains all the methods of ReadWrite
and Lock
, in addition to a Close()
method:
type ReadWrite interface {
Read(b Buffer) bool
Write(b Buffer) bool
}
type Lock interface {
Lock()
Unlock()
}
type File interface {
ReadWrite
Lock
Close()
}
Detecting and converting the type of an interface variable
An interface type variable varI
can contain a value of any type; we must have a means to detect this dynamic type, which is the actual type of the value stored in the variable at run time. The dynamic type may vary during execution but is always assignable to the type of the interface variable itself.
In general, we can test if varI
contains at a certain moment a variable of type T
with the type assertion test:
v := varI.(T) // unchecked type assertion
varI
must be an interface variable. If not, the compiler signals the error: invalid type assertion: varI.(T) (non-interface type (type of varI) on left)
A type assertion may not be valid. The compiler does its utmost best to see if the conversion is valid, but it cannot foresee all possible cases. If this conversion fails while running the program, a runtime error occurs! A safer way is to use the following form:
if v, ok := varI.(T); ok { // checked type assertion
Process(v)
return
}
// here varI is not of type T
If this conversion is valid, v
will contain the value of varI
converted to type T
and ok
will be true. Otherwise, v
is the zero value for T
and ok
is false, so no runtime error occurs!
Note: Always use the comma, ok form for type assertions
In most cases, you would want to test the value of ok in an if. Then, it is most convenient to use the form:
if v, ok := varI.(T); ok {
// ...
}
In this form, shadowing the variable varI
by giving varI
and v
the same name is sometimes done.
An example can be seen below:
Get hands-on with 1400+ tech skills courses.