· 2分で読了

Golang ノート — Type Assertion

この記事は中国語から自動翻訳されたものです。翻訳によりニュアンスが失われている場合があります。

Go言語(golang)において、interface{} 型に対しては型アサーション(Type Assertion)を行うことで、その interface が特定の型であると仮定し、その型のメソッドを操作できるようになる。

var i interface{} = "hello"
s := i.(string)
fmt.Println(s)

このコードは、元の interface{} を文字列としてアサーションできる。

ただし特に注意が必要なのは、もしこの型が文字列でない場合、このコードは即座に panic を引き起こす点だ。

args := []interface{}{
		1,
		"1",
		"2",
	}
for _, arg := args {
  val := arg.(int) // interface conversion: interface {} is string, not int
  fmt.Println(val)
}

Go言語にはある仕組みが用意されており、型アサーションは2つの値を返す。1つは変換後の値、もう1つはそのアサーションが正しいかどうかを示す真偽値だ。

args := []interface{}{
		1,
		"1",
		"2",
	}
for _, arg := args {
  if val, ok := arg.(int); ok {
    fmt.Println(val)    
  } else {
    fmt.Println("not int.")
  }
}

ここまでのところで、注意すべき点が2つある:

  1. 2つ目の戻り値を受け取らない場合、型を完全に確信していない限り、アサーション失敗によってプログラムが panic を起こす可能性がある
  2. 2つ目の戻り値を追加すれば、panic は発生しない

少し面倒ではあるが、やはり常に安全側に倒して型変換を行うのが無難だ。

もう1点注意すべきなのは、アサーションに失敗した後の val は、アサーションしようとした型のゼロ値(zero-value)になるということだ。

アサーション失敗後の val は、アサーションしようとした型のゼロ値になる。

for _, arg := range args {
  if val, ok := arg.(int); ok {
    fmt.Println(val, ok) // 1, true
  } else {
    fmt.Println(val, ok) // 0 , false
    // 0, false
  }
}

一般的にはアサーション失敗後にこの value を使うことはあまりないが、油断していると落とし穴にハマるかもしれない。

関連記事

他のトピックを探索