Golangのインターフェースについてまとめる。
type <型名> interface {
<メソッド名(<引数の型>, ...)(<戻り値の型>, ...)
}
// Ex.
type Human interface {
say() string
}
interface型で宣言された変数はどんな型の値でも代入ができる。
var i interface{}
i = 123
i = "Hello World"
i = []int{1, 2, 3} // etc...
interface型を引数にすると、どんな型の値でも渡すことができる。
package main
import "fmt"
type Human struct {
Name string
Age int
}
func printType(i interface{}) {
fmt.Printf("%T\n", i)
}
func main() {
h := Human{
Name: "John",
Age: 20,
}
printType(h) // main.Human
}
型アサーションの構文。
<変数>.(<型>)
使い方は変数2つを取るような形で使う。
s, ok := i.(Human)
変数iがHuman型であった場合は、変数sはHuman型の変数iの実際の値が、変数okにはtrueが格納される。
逆に、変数iがHuman型ではない場合は、変数sにはHuman型のゼロ値が格納される。
package main
import "fmt"
type Human struct {
Name string
Age int
}
type Alien struct {
Name string
Age int
}
func printOnlyHuman(i interface{}) {
s, ok := i.(Human)
if !ok {
fmt.Printf("%v\n", "Human型ではない")
fmt.Printf("%v\n", s)
return
}
fmt.Printf("%v\n", "Human型である")
fmt.Printf("%v\n", s)
}
func main() {
h := Human{
Name: "John",
Age: 20,
}
a := Alien {
Name: "Tom",
Age: 200000,
}
printOnlyHuman(h) // Human型である。{John 20}
printOnlyHuman(a) // Human型ではない。{ 0}
}
Golangのインターフェースのポピュラーな使用方法である、「異なる型に共通の性質を付与する」使い方の例。
package main
import "fmt"
type Action interface {
say()
}
type Human struct {}
type Alien struct {}
func (h *Human) say() {
fmt.Println("I'm Human")
}
func (a *Alien) say() {
fmt.Println("I'm Alien")
}
func do(a Action) { // Action型を受け取る
a.say()
}
func main() {
ha := []Action{
&Human{},
&Alien{},
}
for _, v := range ha {
do(v)
}
}
関連書籍