Goの勉強 インターフェース

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つ以上の具象型により満足されている場合にだけ使われる。