Go言語では、インターフェース型xから型Tについて、
x.(T)
のような記法を型アサーションと呼びます。 Tがインターフェース型の場合、動的な型xがインターフェースTを実装しているかどうかを確認します。
xがTを実装しているかどうかは実行時に決まるため、失敗する場合があります。 いわゆるダウンキャストに相当する操作をすることができるため、C++のdynamic_castや、WindowsのCOMで言うところのQueryInterfaceに近いイメージだと思います。
型アサーションが以下のように代入や初期化で使われると、(T, bool)のペアを返します。
v, ok := x.(T)
次の例では、FooableとBarableを実装した”Hogus”と、Fooableのみ実装した”Bogus”を作成して、型アサーションによってHogusがBarableにキャストできてBogusができないことを確認しています。
http://play.golang.org/p/GggE7R1yw2
package main
import "fmt"
type Fooable interface {
Foo()
}
type Barable interface {
Bar()
}
type Hocus struct {
format string
}
func NewHocus() (*Hocus) {
b := new(Hocus)
b.format = "-- %s\n"
return b
}
func (self *Hocus) Foo() {
fmt.Printf(self.format, "Hocus Foo")
}
func (self *Hocus) Bar() {
fmt.Printf(self.format, "Hocus Bar")
}
type Bogus struct {
format string
}
func NewBogus() (*Bogus) {
b := new(Bogus)
b.format = "== %s\n"
return b
}
func (self *Bogus) Foo() {
fmt.Printf(self.format, "Bogus Foo")
}
func main() {
testHocus()
testBogus()
}
func testHocus() {
var o Fooable
o = NewHocus()
o.Foo()
p, ok := o.(Barable)
p.Bar()
fmt.Printf("Type assertion result is %t\n", ok)
}
func testBogus() {
var o Fooable
o = NewBogus()
o.Foo()
p, ok := o.(Barable)
fmt.Printf("Bogus Barable is %T\n", p)
fmt.Printf("Type assertion result is %t\n", ok)
}
参考
- http://golang.org/ref/spec#Type_assertions
- http://ja.wikipedia.org/wiki/%E5%9E%8B%E5%A4%89%E6%8F%9B