Go Interfaces
Go interfaces and type assertions
Interfaces
Interfaces provide polymorphism in Go. If different types implement the same methods, an interface can handle them through a common API.
The following interface requires a ToString() method. Person and Book satisfy it automatically because they implement that method.
package main
import "fmt"
type Printable interface {
ToString() string
}
func PrintOut(p Printable) {
fmt.Println(p.ToString())
}
type Person struct { name string }
func (p Person) ToString() string { return p.name }
type Book struct { title string }
func (b Book) ToString() string { return b.title }
func main() {
PrintOut(Person{name: "devkuma"})
PrintOut(Book{title: "Let's study Go."})
}
The interface{} Type
interface{} can receive a value of any type. Since Go 1.18, you can also use its alias, any.
func funcA(a interface{}) {
// ...
}
Use a type assertion to retrieve a specific type.
func funcA(a interface{}) {
fmt.Printf("%d\n", a.(int))
}
A type assertion can return a second Boolean value indicating whether conversion succeeded.
func PrintOut(a interface{}) {
q, ok := a.(Printable)
if ok {
fmt.Println(q.ToString())
} else {
fmt.Println("Not printable.")
}
}
Use a type switch to process different types.
func funcA(a interface{}) {
switch a.(type) {
case bool:
fmt.Printf("%t\n", a)
case int:
fmt.Printf("%d\n", a)
case string:
fmt.Printf("%s\n", a)
}
}
An interface{} value can also store nested map data.
type any interface{}
type dict map[string]any
p1 := dict{
"name": "devkuma",
"address": dict{"tel": "012-3456-7890"},
}
tel := p1["address"].(dict)["tel"]