メインコンテンツにスキップ
モジュール 6 · レッスン 2 / 5コース内の 27/50~10 min
モジュールのレッスン (2/5)

型アサーション

型アサーション は、インターフェイス値から具象型を抽出します。 interface{} (または「高」インターフェイス) がある場合に必要になります。 hand であり、フィールドにアクセスするにはそれを特定のタイプとして扱う必要があるか、 メソッドがインターフェイスに存在しません。

構文

Go
var i interface{} = "ciao"

s := i.(string)           // "panic" form: panics if it's not a string
s, ok := i.(string)       // "comma ok" form: ok = false if it's not a string

2 つの形式、2 つのセマンティクス:

フォーム成功失敗
v := i.(T)v = 型 T の値実行時のパニック
v, ok := i.(T)v=...、ok=truev = T のゼロ値、ok=false

「カンマ OK」形式: 最も安全

Go
var i interface{} = 42

if s, ok := i.(string); ok {
    fmt.Println("è stringa:", s)
} else {
    fmt.Println("non è stringa, ignoro")
}

ok を使用すると、パニックを起こさずに「間違ったタイプ」の場合に対処できます。それは ほとんどの場合、慣用的なパターン。

インターフェースへのアサーション

アサーションは具象型だけでなく、他の型でも機能します。 インターフェース:

Go
type Closer interface { Close() error }

func tryClose(x interface{}) {
    if c, ok := x.(Closer); ok {
        c.Close()
    }
}

標準ライブラリで非常に一般的なパターン: 「入力も io.Closer、最後に Close を呼び出します。」

ポインタと値のアサーション

アサーションは動的タイプと正確に一致する必要があります。

Go
type Cat struct{}
func (c *Cat) Meow() {}

var a interface{} = &Cat{}

c1, ok := a.(*Cat)   // ok = true
c2, ok := a.(Cat)    // ok = false: it holds *Cat, not Cat

*Cat と Cat は、型システムの別個の型です。

アサーションとタイプの切り替えをいつ使用するか

  • 可能なタイプは 1 つだけ、「機能検出」チェック (オプションのインターフェイスへのキャストなど): comma ok を使用した タイプ アサーション。
  • 2 つ以上の可能なタイプ、複数のブランチを介してディスパッチ: タイプ スイッチ (次のレッスン)。

試してみてください

運動#go.m6.l2.e1
試行回数: 0読み込み中…

i から文字列を抽出するには、カンマ ok パターンを使用します。

エディターを読み込み中…
ヒントを表示

構文: `v, ok := i.(T)`。

3 回の試行後に解決策が利用可能になります

運動#go.m6.l2.e2
試行回数: 0読み込み中…

アサーションをカンマなしで int に入力します (i には int が含まれていると仮定します)。

エディターを読み込み中…
ヒントを表示

「ok」を指定しないと、タイプが確実であると想定されます。そうしないとパニックになります。

3 回の試行後に解決策が利用可能になります

Quiz#go.m6.l2.e3
準備完了

i に int が含まれている場合、`s := i.(string)` はどうなりますか?

Go
var i interface{} = 42
s := i.(string)
回答の選択肢

要約

  • v := i.(T): 動的タイプ≠ T の場合にパニックします。
  • v, ok := i.(T): 安全なパターン。ok を確認してください。
  • 別のインターフェイスに対しても機能します (「機能検出」)。
  • T と *T は、アサーションの異なるタイプです。
  • 1 種類 → アサーション; 2+タイプ→タイプスイッチ。