インターフェース #
特定のメソッドを実装した型を抽象型として扱う #
package main
type S1 struct{}
func (s *S1) String() string {
return "S1.String"
}
type S2 struct{}
type S3 struct{}
func (s *S3) String(in string) string {
return "S2.String"
}
type I interface {
String() string
}
func main() {
s1 := new(S1)
s2 := new(S2)
s3 := new(S3)
var i I
// S1 は String メソッドを実装しているので I 型の変数 i に代入できる
i = s1
// S2 は String メソッドを実装していないので I 型の変数 i に代入しようとすると panic になる
i = s2
/*
./prog.go:32:4: cannot use s2 (type *S2) as type I in assignment:
*S2 does not implement I (missing String method)
*/
// S3 は String メソッドを実装しているが引数の型が異なるため I の型の変数 i に代入しようとすると panic になる
i = s3
/*
./prog.go:39:4: cannot use s3 (type *S3) as type I in assignment:
*S3 does not implement I (wrong type for String method)
have String(string) string
want String() string
*/
}
抽象型から具象型への変換をする #
package main
import "fmt"
type S1 struct{}
func (s *S1) String() string {
return "S1.String"
}
type S2 struct{}
func (s *S2) String() string {
return "S2.String"
}
type I interface {
String() string
}
func main() {
s1 := new(S1)
s2 := new(S2)
var i1 I = s1
var i2 I = s2
// タイプアサーションで具象型へ変換
s1_2, ok := i1.(*S1)
fmt.Printf("%#v, %v\n", s1_2, ok) // == &main.S1{}, true
// 変換できない場合は false が返る
s2_2, ok := i1.(*S2)
fmt.Printf("%#v, %v\n", s2_2, ok) // == &main.S1{}, true
// switch で具象型へ変換
switch v := i2.(type) {
case *S2:
fmt.Printf("%#v\n", v) // == &main.S1{}, true
}
}
要求実装のない空の抽象型をAny型として扱う #
interface
に実装するべきメソッドを定義しない場合、どんな型の値も入れられるようになり、他言語でいう Any 型のようにあつかえる。
package main
import "fmt"
func main() {
// 空の interface を作成
var i interface{}
// 任意の値を代入できる
i = 1
i = 1.1
i = "hello"
i = struct{}{}
i = true
fmt.Printf("%#v\n", i) // == true
v, ok := i.(bool)
fmt.Printf("%v, %v\n", v, ok) // == true
}