この遊び場スニペットを参照してください。
関連コード:
type somethingFuncy func(int) bool
func funcy(i int) bool {
return i%2 == 0
}
var a interface{} = funcy
func main() {
_ = a.(func(int) bool) // Works
fmt.Println("Awesome -- apparently, literally specifying the func signature works.")
_ = a.(somethingFuncy) // Panics
fmt.Println("Darn -- doesn't get here. But somethingFuncy is the same signature as func(int) bool.")
}
最初のキャストは、型を明示的に宣言することで機能します。しかし、2番目のキャストはパニックに陥ります。どうして?より長いfuncシグネチャにキャストするクリーンな方法はありますか?
型アサーション(使用する)の場合、実際の型のみが重要です。したがって、somethingFuncy
はsomethingFuncy
にのみ等しく、func(int) bool
ではありません。
まず、これはキャストとは関係ありません。進行中のキャストはありません。 タイプアサーション と タイプ変換 があります。
タイプアサーションを扱っており、タイプconversionsと同じ条件が当てはまると仮定しています。私はあなたの質問を読んでいる間に同じ間違いを犯しましたが、実際には行動に大きな違いがあります。
int
と_type MyInt int
_の2つのタイプがあるとします。これらは両方とも同じ基本タイプ(変換ルールの1つ)を共有するため、変換可能であるため、これは機能します( play ):
_var a int = 10
var b MyInt = MyInt(a)
_
ここで、a
がタイプint
ではなく、タイプ_interface{}
_であるとします( play ):
_var a interface{} = int(10)
var b MyInt = MyInt(a)
_
コンパイラは次のことを通知します。
(type interface {})をMyInt型に変換できません:型アサーションが必要です
そのため、今は変換ではなくアサーションを行っています。これを行う必要があります( play ):
_var a interface{} = int(10)
var b MyInt = a.(MyInt)
_
今、あなたの質問と同じ問題があります。このアサーションはこのパニックで失敗します:
パニック:インターフェース変換:インターフェースはmain.MyIntではなくint
この理由は、仕様の type assertionsセクション に記載されています。
インターフェイスタイプの式xおよびタイプ
T
の場合、プライマリ式x.(T)
は、x
がnil
ではなく、x
に格納されている値がT
タイプであることをアサートします。表記x.(T)
は、タイプアサーションと呼ばれます。 より正確には、T
がインターフェース型ではない場合、x.(T)
はx
の動的型がT
型と同一であることをアサートします。
したがって、int
はMyInt
と同一でなければなりません。 type identity のルールは(他のルールの中で)次のことを述べています:
タイプ名が同じTypeSpecに由来する場合、2つの名前付きタイプは同一です。
int
とMyInt
の宣言は異なるため( TypeSpecs )等しくないため、アサーションは失敗します。 a
をint
にアサートすると、アサーションが機能します。したがって、あなたがしていることは不可能です。
実際のチェックは このコードでは で行われます。これは、両方のタイプが同じであるかどうかを期待どおりにチェックするだけです。
Nemoのすばらしい答えを完成させるために、インターフェースから直接ジャンプすることはできませんが(e.f.、interface{}
)特定の動的タイプ(例:int
)から別のタイプ(例:type MyInt int
)、次の2つの手順を実行できます。
基になる型はその名前が示すようにdynamicであるため、型の表明が成功したか失敗したかをテストすることをお勧めします。一方、型変換の正確性はコンパイラーによって強制されます。
プレイグラウンドスニペットを少し変更しました: http://play.golang.org/p/FZv06Zf7xi
型エイリアスはあなたが望むものだと思います。提案は受け入れられ、Go 1.9で行われるはずです。すなわち。
TypeSpec = identifier [ "=" ] Type .
参照資料
https://github.com/golang/go/issues/181
https://github.com/golang/proposal/blob/master/design/18130-type-alias.md