Go のインターフェース
Go のインターフェースと型アサーション
インターフェース
インターフェースは Go で多態性を実現する。異なる型が同じメソッドを実装していれば、共通の API を通じて扱える。
次のインターフェースは ToString() メソッドを要求する。Person と Book はこのメソッドを実装しているため、自動的に条件を満たす。
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: "Go を学ぼう。"})
}
interface{} 型
interface{} は任意の型の値を受け取れる。Go 1.18 以降では、その別名である any も使用できる。
func funcA(a interface{}) {
// ...
}
特定の型として値を取得するには、型アサーションを使用する。
func funcA(a interface{}) {
fmt.Printf("%d\n", a.(int))
}
型アサーションでは、変換に成功したかを表す真偽値も受け取れる。
func PrintOut(a interface{}) {
q, ok := a.(Printable)
if ok {
fmt.Println(q.ToString())
} else {
fmt.Println("Not printable.")
}
}
型 switch を使うと、型ごとに処理を分けられる。
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)
}
}
interface{} を使うと、入れ子になったマップも表現できる。
type any interface{}
type dict map[string]any
p1 := dict{
"name": "devkuma",
"address": dict{"tel": "012-3456-7890"},
}
tel := p1["address"].(dict)["tel"]