Goの勉強をやり始めたのでメモ。
「プログラミング言語 Go」を読んでる。
契約としてのインターフェース
- GoはStructualTypingを採用している。
- インターフェースを明示的に宣言していなくても、シグネチャを満たしていればそのインターフェースだと見做せる。
インターフェース型
// インターフェースの宣言 type InterfaceName interface { MethodName(args int) bool } // 既存のインターフェースの流用 type InterfaceName2 interface { InterfaceName io.Writer }
インターフェースを満足する
interface{}
は空インターフェースと呼ばれ、どんな値でも入れることができる。
var any interface{} any = 1 any = 'r' any = "string" any = map[string]int{"one", 1} any = new(bytes.Buffer)
以下のようにインターフェースとの関係性を明示的に示すことができる。
var _ io.Writer = (*bytes.Buffer)(nil)
インターフェース値
インターフェース値は
- 動的な型(具象型)
- 動的な値(その型の値)
の2つを持っている。
コード | 型 | 値 |
---|---|---|
var w io.Writer |
nil | nil |
w = os.Stdout |
*os.File | os.Stdoutのコピー |
w = new(bytes.Buffer) |
*bytes.Buffer | 新たな Buffer へのポインタ |
w = nil |
nil | nil |
- インターフェース値の動的な型が何であるかはコンパイル時にはわからない。
- インターフェース値は動的な型が比較可能であれば比較できるし、比較不可能であれば比較できない
- 他の型と違い、比較可能かどうかが型のみで判定できない
- nil ポインタを含むインターフェースは nil ではない
型アサーション
以下のように書くことで、型が別の型がどうか、あるいは満足するかを確認できる。
var w io.Writer = os.stdout f, ok := w.(*os.File)
型switch
型による分岐を以下のように書くことができる。
switch x := x.(type) { case nil : //... case int, uint : //... case bool : //... case string : //... default : //... }
ちょっとした助言
Goでは、インターフェースは2つ以上の具象型により満足されている場合にだけ使われる。