2011年12月20日火曜日

GoのTypeAssertion(型変換?)


私が書いたGo言語プログラミング入門 on Google App Engineにある記述で間違いがあったのですが、正誤表に書くには長いので、この記事に残しておこうと思います。

P.108で「インターフェイスの型の変数に値を代入した後、本来の型に戻す事はできません。」と記述しているのですが、実際は、戻すことが可能です。
具体的な方法は、"変数名.(型)"と記述することで復元します。
Go言語の言語仕様にも、Primary expressionsに記載がありました。

実際の検証用のソースコードです。
動作確認はSDK1.6.1で行いましたので、書籍のベースバージョン1.5.5では未検証ですが、
古いバージョンのSDKで開発される事は減るかと思いますので、検証していません。

以下のソースコードが検証用です。(ほぼツッコミ時に紹介されたソースのままですが…)

package interfacesample3

import (
 "fmt"
 "http"
)

type Introduction interface {
 intro(w http.ResponseWriter)
}

type Coffee struct {
 Sugar bool
}

func (coffee Coffee) intro(w http.ResponseWriter) {
 if coffee.Sugar {
  fmt.Fprintf(w, "This is a coffee with sugar\n")
 } else {
  fmt.Fprintf(w, "This is a black coffee\n")
 }
}

func init() {
 http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
        // Introduction型の配列を作成し、Coffee型のインスタンスを代入する。
 array := make([]Introduction, 1)
 array[0] = new(Coffee)
 array[0].intro(w)

        // そもそもnew関数で返される型はCoffeeではなく、*Coffee!
 var coffee *Coffee
 coffee = array[0].(*Coffee)
 coffee.Sugar = true
 coffee.intro(w)
}

出力結果は
This is a black coffee
This is a coffee with sugar

となり、復元できている事がわかります。

書籍の型の復元については、完全に不勉強でした。
今回は柴田芳樹さんにご指摘いただきました。本当にありがとうございました。