· 2分で読了

Golang ノート — タイプアサーション

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

以下は、指定されたルールに従って翻訳した日本語のテキストです。


golang において、interface{} 型に対して型判定を行うことで、このインターフェースが特定の型であると仮定することができ、そうすることでその型のメソッドを操作することが可能になります。

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

このコードは、元の interface{} を文字列として判定します。

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

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

Golang は、型判定の際に二つの値を返すメカニズムを提供しています。一つは変換後の値、もう一つはこの判定が正しいかどうかです。

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

ここまでで、注意すべき点が二つあります:

  1. 第二の返り値がない場合、型が確実でない限り、型判定の失敗が原因で panic を引き起こす可能性があります。
  2. 第二の返り値を追加することで、panic を引き起こすことはありません。

少々手間ではありますが、型変換は常に保守的に行う方が良いでしょう。

もう一つ注意すべき点は、判定が失敗した場合の val は、判定された型のゼロ値であるということです。

判定失敗後の 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
  }
}

一般的に、判定が失敗した後、この値を使用することはあまりありませんが、注意しないと罠にはまる可能性があります。