[Go言語] Goでのキャスト (型アサーション)

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

Author: _fp

Software Engineer Place: Tokyo, Japan Skills: C, Javascript, Objective-C, Perl, Clojure, Java, PythonErlang, Haskell, OpenGL Twitter: _fp