🌀

Goにおける型アサーションと型変換の違いを理解しよう

に公開

型アサーションと型変換の違いについて ✨

こんにちは!今回はGolangの「型アサーション」と「型変換」について解説します🚀。Goを使っていると、「これって型アサーション?それとも型変換?」と迷うことがありますよね。実際、この2つは似ているようで全然違うんです。

💡 型アサーションとは?

型アサーションとはインタフェース型から具体的な値を取り出すために使います。

例を見てみましょう 👀

package main

import "fmt"

func main() {
	var a any = "hello"

	// any 型から string 型に型アサーション
	s, ok := a.(string)
	if ok {
		fmt.Println("string型です:", s)
	} else {
		fmt.Println("string型ではありません")
	}

	// any 型から int 型に型アサーションして失敗
	_, ok = a.(int)
	if !ok {
		fmt.Println("int型ではありません")
	}
}

👆 このコードでは「カンマ ok イディオム」を用いてany 型の変数 a から string 型を取り出しています。型アサーションは、変数.(型) と記述します。型アサーションに成功すれば、インタフェース型(any または interface{})の値から指定した型(ここでは string)の値を取り出すことができ、okには型アサーションに成功したことを意味するtrueが代入されます。

📝 ポイント: 型アサーションはインタフェース内の値の型を確認しながら安全に取り出すための手法です。型キャストではないので注意しましょう。

✒ なぜ「型アサーション」と呼ぶのか

「assertion(アサーション)」には「断言」という意味があり、型アサーションによって特定の型を取り出せると断言しているのです。

🛠️ 型キャストとは?

一方で型キャストは明示的に型を変換することを指します。例えば、int から float64 へ変換したり、float64 から int へ変換したりします。

例を見てみましょう 👇

package main

import "fmt"

func main() {
	var n int = 42

	// int 型から float64 型に型変換
	var f float64 = float64(n)
	fmt.Printf("intからfloat64へ変換: %f\n", f)

	// float64 型から int 型に型変換
	var i int = int(f)
	fmt.Printf("float64からintへ変換: %d\n", i)
}

👆 このコードでは、intfloat64 に型キャストし、逆に float64 から int に型キャストしています。型キャストは、型(変数)のように記述します。型キャストは値の型そのものを変換するので異なるメモリ表現に変換されます。

📝 ポイント: 型キャストは変数のメモリ表現を変換する操作です。

✒ なぜ「型キャスト」と呼ぶのか

「cast(キャスト)」には「鋳造(金属を溶かして型に流し込んで固める)」という意味があり、金属を任意の形に変換できます。そこから転じてある型の変数を違う型の変数に変換できるという意味になったのです。

✨ 違いを整理しましょう!

  • 型アサーション: インタフェース型から具体的な型を取り出す方法。
    • 利用方法:型アサーションで取り出した値, 型アサーションの成功の有無 := インタフェース型の変数.(型アサーションしたい型)
  • 型変換: 値の型そのものを明示的に変換する方法。
    • 利用方法:型変換された変数 := 型変換したい型(型変換したい変数)
型アサーションと型変換の細かな違い

型アサーションは実行時に判定されますが、一方で型変換はコンパイル時に判定されます。

下記のコードを go build してみてください。不適切な型変換を行っている変数 n3 についてのみ指摘されます。

package main

import "fmt"

func main() {
	var a any = 1
	n, ok := a.(int)
	fmt.Printf("n: %d, ok: %v\n", n, ok)

	var a2 any = "hello"
	n2, ok := a2.(int)
	fmt.Printf("n: %d, ok: %v\n", n2, ok)

	var n3 string = "abc"
	i := int(n3)
	fmt.Printf("i: %d\n", i)

}

変数 n3 周辺を削除したうえで実行すると出力は下記の通りになります。

n: 1, ok: true
n: 0, ok: false

上記の実験から、型変換はコンパイル時、型アサーションは実行時に判定されることがわかります。

型アサーションは、「インタフェース型」から取り出すときにしか使えない点に注意しましょう。逆に、型変換はすべての互換性のある型同士で利用できます。

おわりに 🎉

型アサーションと型変換、どちらもGolangを扱う上で知っておくべき基本的な概念です。それぞれの違いを理解して、適切に使い分けることで、コードがより良くなります!

今回紹介したコードを実際に動かしてみて、ぜひ違いを実感してくださいね!Happy Coding ✨

Discussion